1254721Semaste//===-- Materializer.cpp ----------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Core/Log.h"
11254721Semaste#include "lldb/Core/RegisterValue.h"
12254721Semaste#include "lldb/Core/ValueObjectConstResult.h"
13254721Semaste#include "lldb/Core/ValueObjectVariable.h"
14254721Semaste#include "lldb/Expression/ClangExpressionVariable.h"
15254721Semaste#include "lldb/Expression/Materializer.h"
16254721Semaste#include "lldb/Symbol/ClangASTContext.h"
17254721Semaste#include "lldb/Symbol/Symbol.h"
18254721Semaste#include "lldb/Symbol/Type.h"
19254721Semaste#include "lldb/Symbol/Variable.h"
20254721Semaste#include "lldb/Target/ExecutionContext.h"
21254721Semaste#include "lldb/Target/RegisterContext.h"
22254721Semaste#include "lldb/Target/StackFrame.h"
23254721Semaste#include "lldb/Target/Target.h"
24254721Semaste#include "lldb/Target/Thread.h"
25254721Semaste
26254721Semasteusing namespace lldb_private;
27254721Semaste
28254721Semasteuint32_t
29254721SemasteMaterializer::AddStructMember (Entity &entity)
30254721Semaste{
31254721Semaste    uint32_t size = entity.GetSize();
32254721Semaste    uint32_t alignment = entity.GetAlignment();
33254721Semaste
34254721Semaste    uint32_t ret;
35254721Semaste
36254721Semaste    if (m_current_offset == 0)
37254721Semaste        m_struct_alignment = alignment;
38254721Semaste
39254721Semaste    if (m_current_offset % alignment)
40254721Semaste        m_current_offset += (alignment - (m_current_offset % alignment));
41254721Semaste
42254721Semaste    ret = m_current_offset;
43254721Semaste
44254721Semaste    m_current_offset += size;
45254721Semaste
46254721Semaste    return ret;
47254721Semaste}
48254721Semaste
49254721Semastevoid
50254721SemasteMaterializer::Entity::SetSizeAndAlignmentFromType (ClangASTType &type)
51254721Semaste{
52254721Semaste    m_size = type.GetByteSize();
53254721Semaste
54254721Semaste    uint32_t bit_alignment = type.GetTypeBitAlign();
55254721Semaste
56254721Semaste    if (bit_alignment % 8)
57254721Semaste    {
58254721Semaste        bit_alignment += 8;
59254721Semaste        bit_alignment &= ~((uint32_t)0x111u);
60254721Semaste    }
61254721Semaste
62254721Semaste    m_alignment = bit_alignment / 8;
63254721Semaste}
64254721Semaste
65254721Semasteclass EntityPersistentVariable : public Materializer::Entity
66254721Semaste{
67254721Semastepublic:
68254721Semaste    EntityPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp) :
69254721Semaste        Entity(),
70254721Semaste        m_persistent_variable_sp(persistent_variable_sp)
71254721Semaste    {
72254721Semaste        // Hard-coding to maximum size of a pointer since persistent variables are materialized by reference
73254721Semaste        m_size = 8;
74254721Semaste        m_alignment = 8;
75254721Semaste    }
76254721Semaste
77254721Semaste    void MakeAllocation (IRMemoryMap &map, Error &err)
78254721Semaste    {
79254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
80254721Semaste
81254721Semaste        // Allocate a spare memory area to store the persistent variable's contents.
82254721Semaste
83254721Semaste        Error allocate_error;
84254721Semaste
85254721Semaste        lldb::addr_t mem = map.Malloc(m_persistent_variable_sp->GetByteSize(),
86254721Semaste                                      8,
87254721Semaste                                      lldb::ePermissionsReadable | lldb::ePermissionsWritable,
88254721Semaste                                      IRMemoryMap::eAllocationPolicyMirror,
89254721Semaste                                      allocate_error);
90254721Semaste
91254721Semaste        if (!allocate_error.Success())
92254721Semaste        {
93254721Semaste            err.SetErrorStringWithFormat("couldn't allocate a memory area to store %s: %s", m_persistent_variable_sp->GetName().GetCString(), allocate_error.AsCString());
94254721Semaste            return;
95254721Semaste        }
96254721Semaste
97254721Semaste        if (log)
98254721Semaste            log->Printf("Allocated %s (0x%" PRIx64 ") sucessfully", m_persistent_variable_sp->GetName().GetCString(), mem);
99254721Semaste
100254721Semaste        // Put the location of the spare memory into the live data of the ValueObject.
101254721Semaste
102254721Semaste        m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope(),
103254721Semaste                                                                              m_persistent_variable_sp->GetTypeFromUser(),
104254721Semaste                                                                              m_persistent_variable_sp->GetName(),
105254721Semaste                                                                              mem,
106254721Semaste                                                                              eAddressTypeLoad,
107254721Semaste                                                                              m_persistent_variable_sp->GetByteSize());
108254721Semaste
109254721Semaste        // Clear the flag if the variable will never be deallocated.
110254721Semaste
111254721Semaste        if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
112254721Semaste        {
113254721Semaste            Error leak_error;
114254721Semaste            map.Leak(mem, leak_error);
115254721Semaste            m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation;
116254721Semaste        }
117254721Semaste
118254721Semaste        // Write the contents of the variable to the area.
119254721Semaste
120254721Semaste        Error write_error;
121254721Semaste
122254721Semaste        map.WriteMemory (mem,
123254721Semaste                         m_persistent_variable_sp->GetValueBytes(),
124254721Semaste                         m_persistent_variable_sp->GetByteSize(),
125254721Semaste                         write_error);
126254721Semaste
127254721Semaste        if (!write_error.Success())
128254721Semaste        {
129254721Semaste            err.SetErrorStringWithFormat ("couldn't write %s to the target: %s", m_persistent_variable_sp->GetName().AsCString(),
130254721Semaste                                          write_error.AsCString());
131254721Semaste            return;
132254721Semaste        }
133254721Semaste    }
134254721Semaste
135254721Semaste    void DestroyAllocation (IRMemoryMap &map, Error &err)
136254721Semaste    {
137254721Semaste        Error deallocate_error;
138254721Semaste
139254721Semaste        map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong(), deallocate_error);
140254721Semaste
141254721Semaste        m_persistent_variable_sp->m_live_sp.reset();
142254721Semaste
143254721Semaste        if (!deallocate_error.Success())
144254721Semaste        {
145254721Semaste            err.SetErrorStringWithFormat ("couldn't deallocate memory for %s: %s", m_persistent_variable_sp->GetName().GetCString(), deallocate_error.AsCString());
146254721Semaste        }
147254721Semaste    }
148254721Semaste
149254721Semaste    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
150254721Semaste    {
151254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
152254721Semaste
153254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
154254721Semaste
155254721Semaste        if (log)
156254721Semaste        {
157254721Semaste            log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]",
158254721Semaste                        (uint64_t)load_addr,
159254721Semaste                        m_persistent_variable_sp->GetName().AsCString(),
160254721Semaste                        m_persistent_variable_sp->m_flags);
161254721Semaste        }
162254721Semaste
163254721Semaste        if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation)
164254721Semaste        {
165254721Semaste            MakeAllocation(map, err);
166254721Semaste            m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
167254721Semaste
168254721Semaste            if (!err.Success())
169254721Semaste                return;
170254721Semaste        }
171254721Semaste
172254721Semaste        if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) ||
173254721Semaste            m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated)
174254721Semaste        {
175254721Semaste            Error write_error;
176254721Semaste
177254721Semaste            map.WriteScalarToMemory(load_addr,
178254721Semaste                                    m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(),
179254721Semaste                                    map.GetAddressByteSize(),
180254721Semaste                                    write_error);
181254721Semaste
182254721Semaste            if (!write_error.Success())
183254721Semaste            {
184254721Semaste                err.SetErrorStringWithFormat("couldn't write the location of %s to memory: %s", m_persistent_variable_sp->GetName().AsCString(), write_error.AsCString());
185254721Semaste            }
186254721Semaste        }
187254721Semaste        else
188254721Semaste        {
189254721Semaste            err.SetErrorStringWithFormat("no materialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
190254721Semaste            return;
191254721Semaste        }
192254721Semaste    }
193254721Semaste
194254721Semaste    void Dematerialize (lldb::StackFrameSP &frame_sp,
195254721Semaste                        IRMemoryMap &map,
196254721Semaste                        lldb::addr_t process_address,
197254721Semaste                        lldb::addr_t frame_top,
198254721Semaste                        lldb::addr_t frame_bottom,
199254721Semaste                        Error &err)
200254721Semaste    {
201254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
202254721Semaste
203254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
204254721Semaste
205254721Semaste        if (log)
206254721Semaste        {
207254721Semaste            log->Printf("EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]",
208254721Semaste                        (uint64_t)process_address + m_offset,
209254721Semaste                        m_persistent_variable_sp->GetName().AsCString(),
210254721Semaste                        m_persistent_variable_sp->m_flags);
211254721Semaste        }
212254721Semaste
213254721Semaste        if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) ||
214254721Semaste            (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
215254721Semaste        {
216254721Semaste            if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference &&
217254721Semaste                !m_persistent_variable_sp->m_live_sp)
218254721Semaste            {
219254721Semaste                // If the reference comes from the program, then the ClangExpressionVariable's
220254721Semaste                // live variable data hasn't been set up yet.  Do this now.
221254721Semaste
222254721Semaste                lldb::addr_t location;
223254721Semaste                Error read_error;
224254721Semaste
225254721Semaste                map.ReadPointerFromMemory(&location, load_addr, read_error);
226254721Semaste
227254721Semaste                if (!read_error.Success())
228254721Semaste                {
229254721Semaste                    err.SetErrorStringWithFormat("couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
230254721Semaste                    return;
231254721Semaste                }
232254721Semaste
233254721Semaste                m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope (),
234254721Semaste                                                                                      m_persistent_variable_sp->GetTypeFromUser(),
235254721Semaste                                                                                      m_persistent_variable_sp->GetName(),
236254721Semaste                                                                                      location,
237254721Semaste                                                                                      eAddressTypeLoad,
238254721Semaste                                                                                      m_persistent_variable_sp->GetByteSize());
239254721Semaste
240254721Semaste                if (frame_top != LLDB_INVALID_ADDRESS &&
241254721Semaste                    frame_bottom != LLDB_INVALID_ADDRESS &&
242254721Semaste                    location >= frame_bottom &&
243254721Semaste                    location <= frame_top)
244254721Semaste                {
245254721Semaste                    // If the variable is resident in the stack frame created by the expression,
246254721Semaste                    // then it cannot be relied upon to stay around.  We treat it as needing
247254721Semaste                    // reallocation.
248254721Semaste                    m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
249254721Semaste                    m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
250254721Semaste                    m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
251254721Semaste                    m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVIsProgramReference;
252254721Semaste                }
253254721Semaste            }
254254721Semaste
255254721Semaste            lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong();
256254721Semaste
257254721Semaste            if (!m_persistent_variable_sp->m_live_sp)
258254721Semaste            {
259254721Semaste                err.SetErrorStringWithFormat("couldn't find the memory area used to store %s", m_persistent_variable_sp->GetName().GetCString());
260254721Semaste                return;
261254721Semaste            }
262254721Semaste
263254721Semaste            if (m_persistent_variable_sp->m_live_sp->GetValue().GetValueAddressType() != eAddressTypeLoad)
264254721Semaste            {
265254721Semaste                err.SetErrorStringWithFormat("the address of the memory area for %s is in an incorrect format", m_persistent_variable_sp->GetName().GetCString());
266254721Semaste                return;
267254721Semaste            }
268254721Semaste
269254721Semaste            if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry ||
270254721Semaste                m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
271254721Semaste            {
272254721Semaste                if (log)
273254721Semaste                    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());
274254721Semaste
275254721Semaste                // Read the contents of the spare memory area
276254721Semaste
277254721Semaste                m_persistent_variable_sp->ValueUpdated ();
278254721Semaste
279254721Semaste                Error read_error;
280254721Semaste
281254721Semaste                map.ReadMemory(m_persistent_variable_sp->GetValueBytes(),
282254721Semaste                               mem,
283254721Semaste                               m_persistent_variable_sp->GetByteSize(),
284254721Semaste                               read_error);
285254721Semaste
286254721Semaste                if (!read_error.Success())
287254721Semaste                {
288254721Semaste                    err.SetErrorStringWithFormat ("couldn't read the contents of %s from memory: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
289254721Semaste                    return;
290254721Semaste                }
291254721Semaste
292254721Semaste                m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry;
293254721Semaste            }
294254721Semaste        }
295254721Semaste        else
296254721Semaste        {
297254721Semaste            err.SetErrorStringWithFormat("no dematerialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
298254721Semaste            return;
299254721Semaste        }
300254721Semaste
301254721Semaste        lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
302254721Semaste        if (!process_sp ||
303254721Semaste            !process_sp->CanJIT())
304254721Semaste        {
305254721Semaste            // Allocations are not persistent so persistent variables cannot stay materialized.
306254721Semaste
307254721Semaste            m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
308254721Semaste
309254721Semaste            DestroyAllocation(map, err);
310254721Semaste            if (!err.Success())
311254721Semaste                return;
312254721Semaste        }
313254721Semaste        else if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation &&
314254721Semaste                 !(m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget))
315254721Semaste        {
316254721Semaste            DestroyAllocation(map, err);
317254721Semaste            if (!err.Success())
318254721Semaste                return;
319254721Semaste        }
320254721Semaste    }
321254721Semaste
322254721Semaste    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
323254721Semaste    {
324254721Semaste        StreamString dump_stream;
325254721Semaste
326254721Semaste        Error err;
327254721Semaste
328254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
329254721Semaste
330254721Semaste        dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n", load_addr, m_persistent_variable_sp->GetName().AsCString());
331254721Semaste
332254721Semaste        {
333254721Semaste            dump_stream.Printf("Pointer:\n");
334254721Semaste
335254721Semaste            DataBufferHeap data (m_size, 0);
336254721Semaste
337254721Semaste            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
338254721Semaste
339254721Semaste            if (!err.Success())
340254721Semaste            {
341254721Semaste                dump_stream.Printf("  <could not be read>\n");
342254721Semaste            }
343254721Semaste            else
344254721Semaste            {
345254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
346254721Semaste
347254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
348254721Semaste
349254721Semaste                dump_stream.PutChar('\n');
350254721Semaste            }
351254721Semaste        }
352254721Semaste
353254721Semaste        {
354254721Semaste            dump_stream.Printf("Target:\n");
355254721Semaste
356254721Semaste            lldb::addr_t target_address;
357254721Semaste
358254721Semaste            map.ReadPointerFromMemory (&target_address, load_addr, err);
359254721Semaste
360254721Semaste            if (!err.Success())
361254721Semaste            {
362254721Semaste                dump_stream.Printf("  <could not be read>\n");
363254721Semaste            }
364254721Semaste            else
365254721Semaste            {
366254721Semaste                DataBufferHeap data (m_persistent_variable_sp->GetByteSize(), 0);
367254721Semaste
368254721Semaste                map.ReadMemory(data.GetBytes(), target_address, m_persistent_variable_sp->GetByteSize(), err);
369254721Semaste
370254721Semaste                if (!err.Success())
371254721Semaste                {
372254721Semaste                    dump_stream.Printf("  <could not be read>\n");
373254721Semaste                }
374254721Semaste                else
375254721Semaste                {
376254721Semaste                    DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
377254721Semaste
378254721Semaste                    extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, target_address);
379254721Semaste
380254721Semaste                    dump_stream.PutChar('\n');
381254721Semaste                }
382254721Semaste            }
383254721Semaste        }
384254721Semaste
385254721Semaste        log->PutCString(dump_stream.GetData());
386254721Semaste    }
387254721Semaste
388254721Semaste    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
389254721Semaste    {
390254721Semaste    }
391254721Semasteprivate:
392254721Semaste    lldb::ClangExpressionVariableSP m_persistent_variable_sp;
393254721Semaste};
394254721Semaste
395254721Semasteuint32_t
396254721SemasteMaterializer::AddPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp, Error &err)
397254721Semaste{
398254721Semaste    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
399254721Semaste    iter->reset (new EntityPersistentVariable (persistent_variable_sp));
400254721Semaste    uint32_t ret = AddStructMember(**iter);
401254721Semaste    (*iter)->SetOffset(ret);
402254721Semaste    return ret;
403254721Semaste}
404254721Semaste
405254721Semasteclass EntityVariable : public Materializer::Entity
406254721Semaste{
407254721Semastepublic:
408254721Semaste    EntityVariable (lldb::VariableSP &variable_sp) :
409254721Semaste        Entity(),
410254721Semaste        m_variable_sp(variable_sp),
411254721Semaste        m_is_reference(false),
412254721Semaste        m_temporary_allocation(LLDB_INVALID_ADDRESS),
413254721Semaste        m_temporary_allocation_size(0)
414254721Semaste    {
415254721Semaste        // Hard-coding to maximum size of a pointer since all variables are materialized by reference
416254721Semaste        m_size = 8;
417254721Semaste        m_alignment = 8;
418254721Semaste        m_is_reference = m_variable_sp->GetType()->GetClangForwardType().IsReferenceType();
419254721Semaste    }
420254721Semaste
421254721Semaste    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
422254721Semaste    {
423254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
424254721Semaste
425254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
426254721Semaste        if (log)
427254721Semaste        {
428254721Semaste            log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64 ", m_variable_sp = %s]",
429254721Semaste                        (uint64_t)load_addr,
430254721Semaste                        m_variable_sp->GetName().AsCString());
431254721Semaste        }
432254721Semaste
433254721Semaste        ExecutionContextScope *scope = frame_sp.get();
434254721Semaste
435254721Semaste        if (!scope)
436254721Semaste            scope = map.GetBestExecutionContextScope();
437254721Semaste
438254721Semaste        lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp);
439254721Semaste
440254721Semaste        if (!valobj_sp)
441254721Semaste        {
442254721Semaste            err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
443254721Semaste            return;
444254721Semaste        }
445254721Semaste
446254721Semaste        if (m_is_reference)
447254721Semaste        {
448254721Semaste            DataExtractor valobj_extractor;
449254721Semaste            valobj_sp->GetData(valobj_extractor);
450254721Semaste            lldb::offset_t offset = 0;
451254721Semaste            lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
452254721Semaste
453254721Semaste            Error write_error;
454254721Semaste            map.WritePointerToMemory(load_addr, reference_addr, write_error);
455254721Semaste
456254721Semaste            if (!write_error.Success())
457254721Semaste            {
458254721Semaste                err.SetErrorStringWithFormat("couldn't write the contents of reference variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
459254721Semaste                return;
460254721Semaste            }
461254721Semaste        }
462254721Semaste        else
463254721Semaste        {
464269024Semaste            AddressType address_type = eAddressTypeInvalid;
465269024Semaste            const bool scalar_is_load_address = false;
466269024Semaste            lldb::addr_t addr_of_valobj = valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
467263363Semaste            if (addr_of_valobj != LLDB_INVALID_ADDRESS)
468254721Semaste            {
469254721Semaste                Error write_error;
470263363Semaste                map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
471254721Semaste
472254721Semaste                if (!write_error.Success())
473254721Semaste                {
474254721Semaste                    err.SetErrorStringWithFormat("couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
475254721Semaste                    return;
476254721Semaste                }
477254721Semaste            }
478254721Semaste            else
479254721Semaste            {
480254721Semaste                DataExtractor data;
481254721Semaste                valobj_sp->GetData(data);
482254721Semaste
483254721Semaste                if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
484254721Semaste                {
485254721Semaste                    err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString());
486254721Semaste                    return;
487254721Semaste                }
488254721Semaste
489254721Semaste                if (data.GetByteSize() != m_variable_sp->GetType()->GetByteSize())
490254721Semaste                {
491254721Semaste                    if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false)
492254721Semaste                    {
493254721Semaste                        err.SetErrorStringWithFormat("the variable '%s' has no location, it may have been optimized out", m_variable_sp->GetName().AsCString());
494254721Semaste                    }
495254721Semaste                    else
496254721Semaste                    {
497263367Semaste                        err.SetErrorStringWithFormat("size of variable %s (%" PRIu64 ") disagrees with the ValueObject's size (%" PRIu64 ")",
498263367Semaste                                                     m_variable_sp->GetName().AsCString(),
499263367Semaste                                                     m_variable_sp->GetType()->GetByteSize(),
500263367Semaste                                                     data.GetByteSize());
501254721Semaste                    }
502254721Semaste                    return;
503254721Semaste                }
504254721Semaste
505254721Semaste                size_t bit_align = m_variable_sp->GetType()->GetClangLayoutType().GetTypeBitAlign();
506254721Semaste                size_t byte_align = (bit_align + 7) / 8;
507254721Semaste
508269024Semaste                if (!byte_align)
509269024Semaste                    byte_align = 1;
510269024Semaste
511254721Semaste                Error alloc_error;
512254721Semaste
513254721Semaste                m_temporary_allocation = map.Malloc(data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
514254721Semaste                m_temporary_allocation_size = data.GetByteSize();
515254721Semaste
516254721Semaste                if (!alloc_error.Success())
517254721Semaste                {
518254721Semaste                    err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
519254721Semaste                    return;
520254721Semaste                }
521254721Semaste
522254721Semaste                Error write_error;
523254721Semaste
524254721Semaste                map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error);
525254721Semaste
526254721Semaste                if (!write_error.Success())
527254721Semaste                {
528254721Semaste                    err.SetErrorStringWithFormat("couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
529254721Semaste                    return;
530254721Semaste                }
531254721Semaste
532254721Semaste                Error pointer_write_error;
533254721Semaste
534254721Semaste                map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
535254721Semaste
536254721Semaste                if (!pointer_write_error.Success())
537254721Semaste                {
538254721Semaste                    err.SetErrorStringWithFormat("couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString());
539254721Semaste                }
540254721Semaste            }
541254721Semaste        }
542254721Semaste    }
543254721Semaste
544254721Semaste    void Dematerialize (lldb::StackFrameSP &frame_sp,
545254721Semaste                        IRMemoryMap &map,
546254721Semaste                        lldb::addr_t process_address,
547254721Semaste                        lldb::addr_t frame_top,
548254721Semaste                        lldb::addr_t frame_bottom,
549254721Semaste                        Error &err)
550254721Semaste    {
551254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
552254721Semaste
553254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
554254721Semaste        if (log)
555254721Semaste        {
556254721Semaste            log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 ", m_variable_sp = %s]",
557254721Semaste                        (uint64_t)load_addr,
558254721Semaste                        m_variable_sp->GetName().AsCString());
559254721Semaste        }
560254721Semaste
561254721Semaste        if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
562254721Semaste        {
563254721Semaste            ExecutionContextScope *scope = frame_sp.get();
564254721Semaste
565254721Semaste            if (!scope)
566254721Semaste                scope = map.GetBestExecutionContextScope();
567254721Semaste
568254721Semaste            lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp);
569254721Semaste
570254721Semaste            if (!valobj_sp)
571254721Semaste            {
572254721Semaste                err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
573254721Semaste                return;
574254721Semaste            }
575254721Semaste
576254721Semaste            lldb_private::DataExtractor data;
577254721Semaste
578254721Semaste            Error extract_error;
579254721Semaste
580254721Semaste            map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), extract_error);
581254721Semaste
582254721Semaste            if (!extract_error.Success())
583254721Semaste            {
584254721Semaste                err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->GetName().AsCString());
585254721Semaste                return;
586254721Semaste            }
587254721Semaste
588254721Semaste            Error set_error;
589254721Semaste
590254721Semaste            valobj_sp->SetData(data, set_error);
591254721Semaste
592254721Semaste            if (!set_error.Success())
593254721Semaste            {
594254721Semaste                err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString());
595254721Semaste                return;
596254721Semaste            }
597254721Semaste
598254721Semaste            Error free_error;
599254721Semaste
600254721Semaste            map.Free(m_temporary_allocation, free_error);
601254721Semaste
602254721Semaste            if (!free_error.Success())
603254721Semaste            {
604254721Semaste                err.SetErrorStringWithFormat("couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString());
605254721Semaste                return;
606254721Semaste            }
607254721Semaste
608254721Semaste            m_temporary_allocation = LLDB_INVALID_ADDRESS;
609254721Semaste            m_temporary_allocation_size = 0;
610254721Semaste        }
611254721Semaste    }
612254721Semaste
613254721Semaste    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
614254721Semaste    {
615254721Semaste        StreamString dump_stream;
616254721Semaste
617254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
618254721Semaste        dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
619254721Semaste
620254721Semaste        Error err;
621254721Semaste
622254721Semaste        lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
623254721Semaste
624254721Semaste        {
625254721Semaste            dump_stream.Printf("Pointer:\n");
626254721Semaste
627254721Semaste            DataBufferHeap data (m_size, 0);
628254721Semaste
629254721Semaste            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
630254721Semaste
631254721Semaste            if (!err.Success())
632254721Semaste            {
633254721Semaste                dump_stream.Printf("  <could not be read>\n");
634254721Semaste            }
635254721Semaste            else
636254721Semaste            {
637254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
638254721Semaste
639254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
640254721Semaste
641254721Semaste                lldb::offset_t offset;
642254721Semaste
643254721Semaste                ptr = extractor.GetPointer(&offset);
644254721Semaste
645254721Semaste                dump_stream.PutChar('\n');
646254721Semaste            }
647254721Semaste        }
648254721Semaste
649254721Semaste        if (m_temporary_allocation == LLDB_INVALID_ADDRESS)
650254721Semaste        {
651254721Semaste            dump_stream.Printf("Points to process memory:\n");
652254721Semaste        }
653254721Semaste        else
654254721Semaste        {
655254721Semaste            dump_stream.Printf("Temporary allocation:\n");
656254721Semaste        }
657254721Semaste
658254721Semaste        if (ptr == LLDB_INVALID_ADDRESS)
659254721Semaste        {
660254721Semaste            dump_stream.Printf("  <could not be be found>\n");
661254721Semaste        }
662254721Semaste        else
663254721Semaste        {
664254721Semaste            DataBufferHeap data (m_temporary_allocation_size, 0);
665254721Semaste
666254721Semaste            map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err);
667254721Semaste
668254721Semaste            if (!err.Success())
669254721Semaste            {
670254721Semaste                dump_stream.Printf("  <could not be read>\n");
671254721Semaste            }
672254721Semaste            else
673254721Semaste            {
674254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
675254721Semaste
676254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
677254721Semaste
678254721Semaste                dump_stream.PutChar('\n');
679254721Semaste            }
680254721Semaste        }
681254721Semaste
682254721Semaste        log->PutCString(dump_stream.GetData());
683254721Semaste    }
684254721Semaste
685254721Semaste    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
686254721Semaste    {
687254721Semaste        if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
688254721Semaste        {
689254721Semaste            Error free_error;
690254721Semaste
691254721Semaste            map.Free(m_temporary_allocation, free_error);
692254721Semaste
693254721Semaste            m_temporary_allocation = LLDB_INVALID_ADDRESS;
694254721Semaste            m_temporary_allocation_size = 0;
695254721Semaste        }
696254721Semaste
697254721Semaste    }
698254721Semasteprivate:
699254721Semaste    lldb::VariableSP    m_variable_sp;
700254721Semaste    bool                m_is_reference;
701254721Semaste    lldb::addr_t        m_temporary_allocation;
702254721Semaste    size_t              m_temporary_allocation_size;
703254721Semaste};
704254721Semaste
705254721Semasteuint32_t
706254721SemasteMaterializer::AddVariable (lldb::VariableSP &variable_sp, Error &err)
707254721Semaste{
708254721Semaste    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
709254721Semaste    iter->reset (new EntityVariable (variable_sp));
710254721Semaste    uint32_t ret = AddStructMember(**iter);
711254721Semaste    (*iter)->SetOffset(ret);
712254721Semaste    return ret;
713254721Semaste}
714254721Semaste
715254721Semasteclass EntityResultVariable : public Materializer::Entity
716254721Semaste{
717254721Semastepublic:
718254721Semaste    EntityResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory) :
719254721Semaste        Entity(),
720254721Semaste        m_type(type),
721254721Semaste        m_is_program_reference(is_program_reference),
722254721Semaste        m_keep_in_memory(keep_in_memory),
723254721Semaste        m_temporary_allocation(LLDB_INVALID_ADDRESS),
724254721Semaste        m_temporary_allocation_size(0)
725254721Semaste    {
726254721Semaste        // Hard-coding to maximum size of a pointer since all results are materialized by reference
727254721Semaste        m_size = 8;
728254721Semaste        m_alignment = 8;
729254721Semaste    }
730254721Semaste
731254721Semaste    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
732254721Semaste    {
733254721Semaste        if (!m_is_program_reference)
734254721Semaste        {
735254721Semaste            if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
736254721Semaste            {
737254721Semaste                err.SetErrorString("Trying to create a temporary region for the result but one exists");
738254721Semaste                return;
739254721Semaste            }
740254721Semaste
741254721Semaste            const lldb::addr_t load_addr = process_address + m_offset;
742254721Semaste
743254721Semaste            size_t byte_size = m_type.GetByteSize();
744254721Semaste            size_t bit_align = m_type.GetTypeBitAlign();
745254721Semaste            size_t byte_align = (bit_align + 7) / 8;
746254721Semaste
747269024Semaste            if (!byte_align)
748269024Semaste                byte_align = 1;
749269024Semaste
750254721Semaste            Error alloc_error;
751254721Semaste
752254721Semaste            m_temporary_allocation = map.Malloc(byte_size, byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
753254721Semaste            m_temporary_allocation_size = byte_size;
754254721Semaste
755254721Semaste            if (!alloc_error.Success())
756254721Semaste            {
757254721Semaste                err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString());
758254721Semaste                return;
759254721Semaste            }
760254721Semaste
761254721Semaste            Error pointer_write_error;
762254721Semaste
763254721Semaste            map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
764254721Semaste
765254721Semaste            if (!pointer_write_error.Success())
766254721Semaste            {
767254721Semaste                err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString());
768254721Semaste            }
769254721Semaste        }
770254721Semaste    }
771254721Semaste
772254721Semaste    void Dematerialize (lldb::StackFrameSP &frame_sp,
773254721Semaste                        IRMemoryMap &map,
774254721Semaste                        lldb::addr_t process_address,
775254721Semaste                        lldb::addr_t frame_top,
776254721Semaste                        lldb::addr_t frame_bottom,
777254721Semaste                        Error &err)
778254721Semaste    {
779254721Semaste        err.SetErrorString("Tried to detmaterialize a result variable with the normal Dematerialize method");
780254721Semaste    }
781254721Semaste
782254721Semaste    void Dematerialize (lldb::ClangExpressionVariableSP &result_variable_sp,
783254721Semaste                        lldb::StackFrameSP &frame_sp,
784254721Semaste                        IRMemoryMap &map,
785254721Semaste                        lldb::addr_t process_address,
786254721Semaste                        lldb::addr_t frame_top,
787254721Semaste                        lldb::addr_t frame_bottom,
788254721Semaste                        Error &err)
789254721Semaste    {
790254721Semaste        err.Clear();
791254721Semaste
792254721Semaste        ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
793254721Semaste
794254721Semaste        if (!exe_scope)
795254721Semaste        {
796254721Semaste            err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope");
797254721Semaste            return;
798254721Semaste        }
799254721Semaste
800254721Semaste        lldb::addr_t address;
801254721Semaste        Error read_error;
802254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
803254721Semaste
804254721Semaste        map.ReadPointerFromMemory (&address, load_addr, read_error);
805254721Semaste
806254721Semaste        if (!read_error.Success())
807254721Semaste        {
808254721Semaste            err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address");
809254721Semaste            return;
810254721Semaste        }
811254721Semaste
812254721Semaste        lldb::TargetSP target_sp = exe_scope->CalculateTarget();
813254721Semaste
814254721Semaste        if (!target_sp)
815254721Semaste        {
816254721Semaste            err.SetErrorString("Couldn't dematerialize a result variable: no target");
817254721Semaste            return;
818254721Semaste        }
819254721Semaste
820254721Semaste        ConstString name = target_sp->GetPersistentVariables().GetNextPersistentVariableName();
821254721Semaste
822254721Semaste        lldb::ClangExpressionVariableSP ret;
823254721Semaste
824254721Semaste        ret = target_sp->GetPersistentVariables().CreateVariable(exe_scope,
825254721Semaste                                                                 name,
826254721Semaste                                                                 m_type,
827254721Semaste                                                                 map.GetByteOrder(),
828254721Semaste                                                                 map.GetAddressByteSize());
829254721Semaste
830254721Semaste        if (!ret)
831254721Semaste        {
832254721Semaste            err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString());
833254721Semaste            return;
834254721Semaste        }
835254721Semaste
836254721Semaste        lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
837254721Semaste
838254721Semaste        bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top));
839254721Semaste
840254721Semaste        if (can_persist && m_keep_in_memory)
841254721Semaste        {
842254721Semaste            ret->m_live_sp = ValueObjectConstResult::Create(exe_scope,
843254721Semaste                                                            m_type,
844254721Semaste                                                            name,
845254721Semaste                                                            address,
846254721Semaste                                                            eAddressTypeLoad,
847263363Semaste                                                            map.GetAddressByteSize());
848254721Semaste        }
849254721Semaste
850254721Semaste        ret->ValueUpdated();
851254721Semaste
852254721Semaste        const size_t pvar_byte_size = ret->GetByteSize();
853254721Semaste        uint8_t *pvar_data = ret->GetValueBytes();
854254721Semaste
855254721Semaste        map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
856254721Semaste
857254721Semaste        if (!read_error.Success())
858254721Semaste        {
859254721Semaste            err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory");
860254721Semaste            return;
861254721Semaste        }
862254721Semaste
863254721Semaste        result_variable_sp = ret;
864254721Semaste
865254721Semaste        if (!can_persist || !m_keep_in_memory)
866254721Semaste        {
867254721Semaste            ret->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
868254721Semaste
869254721Semaste            if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
870254721Semaste            {
871254721Semaste                Error free_error;
872254721Semaste                map.Free(m_temporary_allocation, free_error);
873254721Semaste            }
874254721Semaste        }
875254721Semaste        else
876254721Semaste        {
877254721Semaste            ret->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
878254721Semaste        }
879254721Semaste
880254721Semaste        m_temporary_allocation = LLDB_INVALID_ADDRESS;
881254721Semaste        m_temporary_allocation_size = 0;
882254721Semaste    }
883254721Semaste
884254721Semaste    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
885254721Semaste    {
886254721Semaste        StreamString dump_stream;
887254721Semaste
888254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
889254721Semaste
890254721Semaste        dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
891254721Semaste
892254721Semaste        Error err;
893254721Semaste
894254721Semaste        lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
895254721Semaste
896254721Semaste        {
897254721Semaste            dump_stream.Printf("Pointer:\n");
898254721Semaste
899254721Semaste            DataBufferHeap data (m_size, 0);
900254721Semaste
901254721Semaste            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
902254721Semaste
903254721Semaste            if (!err.Success())
904254721Semaste            {
905254721Semaste                dump_stream.Printf("  <could not be read>\n");
906254721Semaste            }
907254721Semaste            else
908254721Semaste            {
909254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
910254721Semaste
911254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
912254721Semaste
913254721Semaste                lldb::offset_t offset;
914254721Semaste
915254721Semaste                ptr = extractor.GetPointer(&offset);
916254721Semaste
917254721Semaste                dump_stream.PutChar('\n');
918254721Semaste            }
919254721Semaste        }
920254721Semaste
921254721Semaste        if (m_temporary_allocation == LLDB_INVALID_ADDRESS)
922254721Semaste        {
923254721Semaste            dump_stream.Printf("Points to process memory:\n");
924254721Semaste        }
925254721Semaste        else
926254721Semaste        {
927254721Semaste            dump_stream.Printf("Temporary allocation:\n");
928254721Semaste        }
929254721Semaste
930254721Semaste        if (ptr == LLDB_INVALID_ADDRESS)
931254721Semaste        {
932254721Semaste            dump_stream.Printf("  <could not be be found>\n");
933254721Semaste        }
934254721Semaste        else
935254721Semaste        {
936254721Semaste            DataBufferHeap data (m_temporary_allocation_size, 0);
937254721Semaste
938254721Semaste            map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err);
939254721Semaste
940254721Semaste            if (!err.Success())
941254721Semaste            {
942254721Semaste                dump_stream.Printf("  <could not be read>\n");
943254721Semaste            }
944254721Semaste            else
945254721Semaste            {
946254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
947254721Semaste
948254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
949254721Semaste
950254721Semaste                dump_stream.PutChar('\n');
951254721Semaste            }
952254721Semaste        }
953254721Semaste
954254721Semaste        log->PutCString(dump_stream.GetData());
955254721Semaste    }
956254721Semaste
957254721Semaste    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
958254721Semaste    {
959254721Semaste        if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS)
960254721Semaste        {
961254721Semaste            Error free_error;
962254721Semaste
963254721Semaste            map.Free(m_temporary_allocation, free_error);
964254721Semaste        }
965254721Semaste
966254721Semaste        m_temporary_allocation = LLDB_INVALID_ADDRESS;
967254721Semaste        m_temporary_allocation_size = 0;
968254721Semaste    }
969254721Semasteprivate:
970254721Semaste    TypeFromUser    m_type;
971254721Semaste    bool            m_is_program_reference;
972254721Semaste    bool            m_keep_in_memory;
973254721Semaste
974254721Semaste    lldb::addr_t    m_temporary_allocation;
975254721Semaste    size_t          m_temporary_allocation_size;
976254721Semaste};
977254721Semaste
978254721Semasteuint32_t
979254721SemasteMaterializer::AddResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory, Error &err)
980254721Semaste{
981254721Semaste    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
982254721Semaste    iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory));
983254721Semaste    uint32_t ret = AddStructMember(**iter);
984254721Semaste    (*iter)->SetOffset(ret);
985254721Semaste    m_result_entity = iter->get();
986254721Semaste    return ret;
987254721Semaste}
988254721Semaste
989254721Semasteclass EntitySymbol : public Materializer::Entity
990254721Semaste{
991254721Semastepublic:
992254721Semaste    EntitySymbol (const Symbol &symbol) :
993254721Semaste        Entity(),
994254721Semaste        m_symbol(symbol)
995254721Semaste    {
996254721Semaste        // Hard-coding to maximum size of a symbol
997254721Semaste        m_size = 8;
998254721Semaste        m_alignment = 8;
999254721Semaste    }
1000254721Semaste
1001254721Semaste    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
1002254721Semaste    {
1003254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1004254721Semaste
1005254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1006254721Semaste
1007254721Semaste        if (log)
1008254721Semaste        {
1009254721Semaste            log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 ", m_symbol = %s]",
1010254721Semaste                        (uint64_t)load_addr,
1011254721Semaste                        m_symbol.GetName().AsCString());
1012254721Semaste        }
1013254721Semaste
1014254721Semaste        Address &sym_address = m_symbol.GetAddress();
1015254721Semaste
1016254721Semaste        ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
1017254721Semaste
1018254721Semaste        lldb::TargetSP target_sp;
1019254721Semaste
1020254721Semaste        if (exe_scope)
1021254721Semaste            target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
1022254721Semaste
1023254721Semaste        if (!target_sp)
1024254721Semaste        {
1025254721Semaste            err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString());
1026254721Semaste            return;
1027254721Semaste        }
1028254721Semaste
1029254721Semaste        lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
1030254721Semaste
1031254721Semaste        if (resolved_address == LLDB_INVALID_ADDRESS)
1032254721Semaste            resolved_address = sym_address.GetFileAddress();
1033254721Semaste
1034254721Semaste        Error pointer_write_error;
1035254721Semaste
1036254721Semaste        map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
1037254721Semaste
1038254721Semaste        if (!pointer_write_error.Success())
1039254721Semaste        {
1040254721Semaste            err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
1041254721Semaste            return;
1042254721Semaste        }
1043254721Semaste    }
1044254721Semaste
1045254721Semaste    void Dematerialize (lldb::StackFrameSP &frame_sp,
1046254721Semaste                        IRMemoryMap &map,
1047254721Semaste                        lldb::addr_t process_address,
1048254721Semaste                        lldb::addr_t frame_top,
1049254721Semaste                        lldb::addr_t frame_bottom,
1050254721Semaste                        Error &err)
1051254721Semaste    {
1052254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1053254721Semaste
1054254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1055254721Semaste
1056254721Semaste        if (log)
1057254721Semaste        {
1058254721Semaste            log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 ", m_symbol = %s]",
1059254721Semaste                        (uint64_t)load_addr,
1060254721Semaste                        m_symbol.GetName().AsCString());
1061254721Semaste        }
1062254721Semaste
1063254721Semaste        // no work needs to be done
1064254721Semaste    }
1065254721Semaste
1066254721Semaste    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
1067254721Semaste    {
1068254721Semaste        StreamString dump_stream;
1069254721Semaste
1070254721Semaste        Error err;
1071254721Semaste
1072254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1073254721Semaste
1074254721Semaste        dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, m_symbol.GetName().AsCString());
1075254721Semaste
1076254721Semaste        {
1077254721Semaste            dump_stream.Printf("Pointer:\n");
1078254721Semaste
1079254721Semaste            DataBufferHeap data (m_size, 0);
1080254721Semaste
1081254721Semaste            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1082254721Semaste
1083254721Semaste            if (!err.Success())
1084254721Semaste            {
1085254721Semaste                dump_stream.Printf("  <could not be read>\n");
1086254721Semaste            }
1087254721Semaste            else
1088254721Semaste            {
1089254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
1090254721Semaste
1091254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
1092254721Semaste
1093254721Semaste                dump_stream.PutChar('\n');
1094254721Semaste            }
1095254721Semaste        }
1096254721Semaste
1097254721Semaste        log->PutCString(dump_stream.GetData());
1098254721Semaste    }
1099254721Semaste
1100254721Semaste    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
1101254721Semaste    {
1102254721Semaste    }
1103254721Semasteprivate:
1104254721Semaste    Symbol m_symbol;
1105254721Semaste};
1106254721Semaste
1107254721Semasteuint32_t
1108254721SemasteMaterializer::AddSymbol (const Symbol &symbol_sp, Error &err)
1109254721Semaste{
1110254721Semaste    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1111254721Semaste    iter->reset (new EntitySymbol (symbol_sp));
1112254721Semaste    uint32_t ret = AddStructMember(**iter);
1113254721Semaste    (*iter)->SetOffset(ret);
1114254721Semaste    return ret;
1115254721Semaste}
1116254721Semaste
1117254721Semasteclass EntityRegister : public Materializer::Entity
1118254721Semaste{
1119254721Semastepublic:
1120254721Semaste    EntityRegister (const RegisterInfo &register_info) :
1121254721Semaste        Entity(),
1122254721Semaste        m_register_info(register_info)
1123254721Semaste    {
1124254721Semaste        // Hard-coding alignment conservatively
1125254721Semaste        m_size = m_register_info.byte_size;
1126254721Semaste        m_alignment = m_register_info.byte_size;
1127254721Semaste    }
1128254721Semaste
1129254721Semaste    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
1130254721Semaste    {
1131254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1132254721Semaste
1133254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1134254721Semaste
1135254721Semaste        if (log)
1136254721Semaste        {
1137254721Semaste            log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 ", m_register_info = %s]",
1138254721Semaste                        (uint64_t)load_addr,
1139254721Semaste                        m_register_info.name);
1140254721Semaste        }
1141254721Semaste
1142254721Semaste        RegisterValue reg_value;
1143254721Semaste
1144254721Semaste        if (!frame_sp.get())
1145254721Semaste        {
1146254721Semaste            err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name);
1147254721Semaste            return;
1148254721Semaste        }
1149254721Semaste
1150254721Semaste        lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1151254721Semaste
1152254721Semaste        if (!reg_context_sp->ReadRegister(&m_register_info, reg_value))
1153254721Semaste        {
1154254721Semaste            err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name);
1155254721Semaste            return;
1156254721Semaste        }
1157254721Semaste
1158254721Semaste        DataExtractor register_data;
1159254721Semaste
1160254721Semaste        if (!reg_value.GetData(register_data))
1161254721Semaste        {
1162254721Semaste            err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name);
1163254721Semaste            return;
1164254721Semaste        }
1165254721Semaste
1166254721Semaste        if (register_data.GetByteSize() != m_register_info.byte_size)
1167254721Semaste        {
1168254721Semaste            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);
1169254721Semaste            return;
1170254721Semaste        }
1171254721Semaste
1172254721Semaste        m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize()));
1173254721Semaste
1174254721Semaste        Error write_error;
1175254721Semaste
1176254721Semaste        map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error);
1177254721Semaste
1178254721Semaste        if (!write_error.Success())
1179254721Semaste        {
1180254721Semaste            err.SetErrorStringWithFormat("couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString());
1181254721Semaste            return;
1182254721Semaste        }
1183254721Semaste    }
1184254721Semaste
1185254721Semaste    void Dematerialize (lldb::StackFrameSP &frame_sp,
1186254721Semaste                        IRMemoryMap &map,
1187254721Semaste                        lldb::addr_t process_address,
1188254721Semaste                        lldb::addr_t frame_top,
1189254721Semaste                        lldb::addr_t frame_bottom,
1190254721Semaste                        Error &err)
1191254721Semaste    {
1192254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1193254721Semaste
1194254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1195254721Semaste
1196254721Semaste        if (log)
1197254721Semaste        {
1198254721Semaste            log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]",
1199254721Semaste                        (uint64_t)load_addr,
1200254721Semaste                        m_register_info.name);
1201254721Semaste        }
1202254721Semaste
1203254721Semaste        Error extract_error;
1204254721Semaste
1205254721Semaste        DataExtractor register_data;
1206254721Semaste
1207254721Semaste        if (!frame_sp.get())
1208254721Semaste        {
1209254721Semaste            err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name);
1210254721Semaste            return;
1211254721Semaste        }
1212254721Semaste
1213254721Semaste        lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1214254721Semaste
1215254721Semaste        map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error);
1216254721Semaste
1217254721Semaste        if (!extract_error.Success())
1218254721Semaste        {
1219254721Semaste            err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString());
1220254721Semaste            return;
1221254721Semaste        }
1222254721Semaste
1223254721Semaste        if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize()))
1224254721Semaste        {
1225254721Semaste            // No write required, and in particular we avoid errors if the register wasn't writable
1226254721Semaste
1227254721Semaste            m_register_contents.reset();
1228254721Semaste            return;
1229254721Semaste        }
1230254721Semaste
1231254721Semaste        m_register_contents.reset();
1232254721Semaste
1233254721Semaste        RegisterValue register_value (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder());
1234254721Semaste
1235254721Semaste        if (!reg_context_sp->WriteRegister(&m_register_info, register_value))
1236254721Semaste        {
1237254721Semaste            err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name);
1238254721Semaste            return;
1239254721Semaste        }
1240254721Semaste    }
1241254721Semaste
1242254721Semaste    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
1243254721Semaste    {
1244254721Semaste        StreamString dump_stream;
1245254721Semaste
1246254721Semaste        Error err;
1247254721Semaste
1248254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1249254721Semaste
1250254721Semaste
1251254721Semaste        dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, m_register_info.name);
1252254721Semaste
1253254721Semaste        {
1254254721Semaste            dump_stream.Printf("Value:\n");
1255254721Semaste
1256254721Semaste            DataBufferHeap data (m_size, 0);
1257254721Semaste
1258254721Semaste            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1259254721Semaste
1260254721Semaste            if (!err.Success())
1261254721Semaste            {
1262254721Semaste                dump_stream.Printf("  <could not be read>\n");
1263254721Semaste            }
1264254721Semaste            else
1265254721Semaste            {
1266254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
1267254721Semaste
1268254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
1269254721Semaste
1270254721Semaste                dump_stream.PutChar('\n');
1271254721Semaste            }
1272254721Semaste        }
1273254721Semaste
1274254721Semaste        log->PutCString(dump_stream.GetData());
1275254721Semaste    }
1276254721Semaste
1277254721Semaste    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
1278254721Semaste    {
1279254721Semaste    }
1280254721Semasteprivate:
1281254721Semaste    RegisterInfo m_register_info;
1282254721Semaste    lldb::DataBufferSP m_register_contents;
1283254721Semaste};
1284254721Semaste
1285254721Semasteuint32_t
1286254721SemasteMaterializer::AddRegister (const RegisterInfo &register_info, Error &err)
1287254721Semaste{
1288254721Semaste    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1289254721Semaste    iter->reset (new EntityRegister (register_info));
1290254721Semaste    uint32_t ret = AddStructMember(**iter);
1291254721Semaste    (*iter)->SetOffset(ret);
1292254721Semaste    return ret;
1293254721Semaste}
1294254721Semaste
1295254721SemasteMaterializer::Materializer () :
1296254721Semaste    m_dematerializer_wp(),
1297254721Semaste    m_result_entity(NULL),
1298254721Semaste    m_current_offset(0),
1299254721Semaste    m_struct_alignment(8)
1300254721Semaste{
1301254721Semaste}
1302254721Semaste
1303254721SemasteMaterializer::~Materializer ()
1304254721Semaste{
1305254721Semaste    DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1306254721Semaste
1307254721Semaste    if (dematerializer_sp)
1308254721Semaste        dematerializer_sp->Wipe();
1309254721Semaste}
1310254721Semaste
1311254721SemasteMaterializer::DematerializerSP
1312254721SemasteMaterializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error)
1313254721Semaste{
1314254721Semaste    ExecutionContextScope *exe_scope = frame_sp.get();
1315254721Semaste
1316254721Semaste    if (!exe_scope)
1317254721Semaste        exe_scope = map.GetBestExecutionContextScope();
1318254721Semaste
1319254721Semaste    DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1320254721Semaste
1321254721Semaste    if (dematerializer_sp)
1322254721Semaste    {
1323254721Semaste        error.SetErrorToGenericError();
1324254721Semaste        error.SetErrorString("Couldn't materialize: already materialized");
1325254721Semaste    }
1326254721Semaste
1327254721Semaste    DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address));
1328254721Semaste
1329254721Semaste    if (!exe_scope)
1330254721Semaste    {
1331254721Semaste        error.SetErrorToGenericError();
1332254721Semaste        error.SetErrorString("Couldn't materialize: target doesn't exist");
1333254721Semaste    }
1334254721Semaste
1335254721Semaste    for (EntityUP &entity_up : m_entities)
1336254721Semaste    {
1337254721Semaste        entity_up->Materialize(frame_sp, map, process_address, error);
1338254721Semaste
1339254721Semaste        if (!error.Success())
1340254721Semaste            return DematerializerSP();
1341254721Semaste    }
1342254721Semaste
1343254721Semaste    if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
1344254721Semaste    {
1345254721Semaste        log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", frame_sp.get(), process_address);
1346254721Semaste        for (EntityUP &entity_up : m_entities)
1347254721Semaste            entity_up->DumpToLog(map, process_address, log);
1348254721Semaste    }
1349254721Semaste
1350254721Semaste    m_dematerializer_wp = ret;
1351254721Semaste
1352254721Semaste    return ret;
1353254721Semaste}
1354254721Semaste
1355254721Semastevoid
1356254721SemasteMaterializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_bottom, lldb::addr_t frame_top)
1357254721Semaste{
1358254721Semaste    lldb::StackFrameSP frame_sp;
1359254721Semaste
1360254721Semaste    lldb::ThreadSP thread_sp = m_thread_wp.lock();
1361254721Semaste    if (thread_sp)
1362254721Semaste        frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
1363254721Semaste
1364254721Semaste    ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope();
1365254721Semaste
1366254721Semaste    if (!IsValid())
1367254721Semaste    {
1368254721Semaste        error.SetErrorToGenericError();
1369254721Semaste        error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
1370254721Semaste    }
1371254721Semaste
1372254721Semaste    if (!exe_scope)
1373254721Semaste    {
1374254721Semaste        error.SetErrorToGenericError();
1375254721Semaste        error.SetErrorString("Couldn't dematerialize: target is gone");
1376254721Semaste    }
1377254721Semaste    else
1378254721Semaste    {
1379254721Semaste        if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
1380254721Semaste        {
1381254721Semaste            log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", frame_sp.get(), m_process_address);
1382254721Semaste            for (EntityUP &entity_up : m_materializer->m_entities)
1383254721Semaste                entity_up->DumpToLog(*m_map, m_process_address, log);
1384254721Semaste        }
1385254721Semaste
1386254721Semaste        for (EntityUP &entity_up : m_materializer->m_entities)
1387254721Semaste        {
1388254721Semaste            if (entity_up.get() == m_materializer->m_result_entity)
1389254721Semaste            {
1390254721Semaste                static_cast<EntityResultVariable*>(m_materializer->m_result_entity)->Dematerialize (result_sp, frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
1391254721Semaste            }
1392254721Semaste            else
1393254721Semaste            {
1394254721Semaste                entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
1395254721Semaste            }
1396254721Semaste
1397254721Semaste            if (!error.Success())
1398254721Semaste                break;
1399254721Semaste        }
1400254721Semaste    }
1401254721Semaste
1402254721Semaste    Wipe();
1403254721Semaste}
1404254721Semaste
1405254721Semastevoid
1406254721SemasteMaterializer::Dematerializer::Wipe ()
1407254721Semaste{
1408254721Semaste    if (!IsValid())
1409254721Semaste        return;
1410254721Semaste
1411254721Semaste    for (EntityUP &entity_up : m_materializer->m_entities)
1412254721Semaste    {
1413254721Semaste        entity_up->Wipe (*m_map, m_process_address);
1414254721Semaste    }
1415254721Semaste
1416254721Semaste    m_materializer = NULL;
1417254721Semaste    m_map = NULL;
1418254721Semaste    m_process_address = LLDB_INVALID_ADDRESS;
1419254721Semaste}
1420