Materializer.cpp revision 254721
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        {
464254721Semaste            Error get_address_error;
465254721Semaste            lldb::ValueObjectSP addr_of_valobj_sp = valobj_sp->AddressOf(get_address_error);
466254721Semaste            if (get_address_error.Success())
467254721Semaste            {
468254721Semaste                DataExtractor valobj_extractor;
469254721Semaste                addr_of_valobj_sp->GetData(valobj_extractor);
470254721Semaste                lldb::offset_t offset = 0;
471254721Semaste                lldb::addr_t addr_of_valobj_addr = valobj_extractor.GetAddress(&offset);
472254721Semaste
473254721Semaste                Error write_error;
474254721Semaste                map.WritePointerToMemory(load_addr, addr_of_valobj_addr, write_error);
475254721Semaste
476254721Semaste                if (!write_error.Success())
477254721Semaste                {
478254721Semaste                    err.SetErrorStringWithFormat("couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
479254721Semaste                    return;
480254721Semaste                }
481254721Semaste            }
482254721Semaste            else
483254721Semaste            {
484254721Semaste                DataExtractor data;
485254721Semaste                valobj_sp->GetData(data);
486254721Semaste
487254721Semaste                if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
488254721Semaste                {
489254721Semaste                    err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString());
490254721Semaste                    return;
491254721Semaste                }
492254721Semaste
493254721Semaste                if (data.GetByteSize() != m_variable_sp->GetType()->GetByteSize())
494254721Semaste                {
495254721Semaste                    if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false)
496254721Semaste                    {
497254721Semaste                        err.SetErrorStringWithFormat("the variable '%s' has no location, it may have been optimized out", m_variable_sp->GetName().AsCString());
498254721Semaste                    }
499254721Semaste                    else
500254721Semaste                    {
501254721Semaste                        err.SetErrorStringWithFormat("size of variable %s disagrees with the ValueObject's size", m_variable_sp->GetName().AsCString());
502254721Semaste                    }
503254721Semaste                    return;
504254721Semaste                }
505254721Semaste
506254721Semaste                size_t bit_align = m_variable_sp->GetType()->GetClangLayoutType().GetTypeBitAlign();
507254721Semaste                size_t byte_align = (bit_align + 7) / 8;
508254721Semaste
509254721Semaste                Error alloc_error;
510254721Semaste
511254721Semaste                m_temporary_allocation = map.Malloc(data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
512254721Semaste                m_temporary_allocation_size = data.GetByteSize();
513254721Semaste
514254721Semaste                if (!alloc_error.Success())
515254721Semaste                {
516254721Semaste                    err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
517254721Semaste                    return;
518254721Semaste                }
519254721Semaste
520254721Semaste                Error write_error;
521254721Semaste
522254721Semaste                map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error);
523254721Semaste
524254721Semaste                if (!write_error.Success())
525254721Semaste                {
526254721Semaste                    err.SetErrorStringWithFormat("couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
527254721Semaste                    return;
528254721Semaste                }
529254721Semaste
530254721Semaste                Error pointer_write_error;
531254721Semaste
532254721Semaste                map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
533254721Semaste
534254721Semaste                if (!pointer_write_error.Success())
535254721Semaste                {
536254721Semaste                    err.SetErrorStringWithFormat("couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString());
537254721Semaste                }
538254721Semaste            }
539254721Semaste        }
540254721Semaste    }
541254721Semaste
542254721Semaste    void Dematerialize (lldb::StackFrameSP &frame_sp,
543254721Semaste                        IRMemoryMap &map,
544254721Semaste                        lldb::addr_t process_address,
545254721Semaste                        lldb::addr_t frame_top,
546254721Semaste                        lldb::addr_t frame_bottom,
547254721Semaste                        Error &err)
548254721Semaste    {
549254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
550254721Semaste
551254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
552254721Semaste        if (log)
553254721Semaste        {
554254721Semaste            log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 ", m_variable_sp = %s]",
555254721Semaste                        (uint64_t)load_addr,
556254721Semaste                        m_variable_sp->GetName().AsCString());
557254721Semaste        }
558254721Semaste
559254721Semaste        if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
560254721Semaste        {
561254721Semaste            ExecutionContextScope *scope = frame_sp.get();
562254721Semaste
563254721Semaste            if (!scope)
564254721Semaste                scope = map.GetBestExecutionContextScope();
565254721Semaste
566254721Semaste            lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp);
567254721Semaste
568254721Semaste            if (!valobj_sp)
569254721Semaste            {
570254721Semaste                err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
571254721Semaste                return;
572254721Semaste            }
573254721Semaste
574254721Semaste            lldb_private::DataExtractor data;
575254721Semaste
576254721Semaste            Error extract_error;
577254721Semaste
578254721Semaste            map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), extract_error);
579254721Semaste
580254721Semaste            if (!extract_error.Success())
581254721Semaste            {
582254721Semaste                err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->GetName().AsCString());
583254721Semaste                return;
584254721Semaste            }
585254721Semaste
586254721Semaste            Error set_error;
587254721Semaste
588254721Semaste            valobj_sp->SetData(data, set_error);
589254721Semaste
590254721Semaste            if (!set_error.Success())
591254721Semaste            {
592254721Semaste                err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString());
593254721Semaste                return;
594254721Semaste            }
595254721Semaste
596254721Semaste            Error free_error;
597254721Semaste
598254721Semaste            map.Free(m_temporary_allocation, free_error);
599254721Semaste
600254721Semaste            if (!free_error.Success())
601254721Semaste            {
602254721Semaste                err.SetErrorStringWithFormat("couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString());
603254721Semaste                return;
604254721Semaste            }
605254721Semaste
606254721Semaste            m_temporary_allocation = LLDB_INVALID_ADDRESS;
607254721Semaste            m_temporary_allocation_size = 0;
608254721Semaste        }
609254721Semaste    }
610254721Semaste
611254721Semaste    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
612254721Semaste    {
613254721Semaste        StreamString dump_stream;
614254721Semaste
615254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
616254721Semaste        dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
617254721Semaste
618254721Semaste        Error err;
619254721Semaste
620254721Semaste        lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
621254721Semaste
622254721Semaste        {
623254721Semaste            dump_stream.Printf("Pointer:\n");
624254721Semaste
625254721Semaste            DataBufferHeap data (m_size, 0);
626254721Semaste
627254721Semaste            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
628254721Semaste
629254721Semaste            if (!err.Success())
630254721Semaste            {
631254721Semaste                dump_stream.Printf("  <could not be read>\n");
632254721Semaste            }
633254721Semaste            else
634254721Semaste            {
635254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
636254721Semaste
637254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
638254721Semaste
639254721Semaste                lldb::offset_t offset;
640254721Semaste
641254721Semaste                ptr = extractor.GetPointer(&offset);
642254721Semaste
643254721Semaste                dump_stream.PutChar('\n');
644254721Semaste            }
645254721Semaste        }
646254721Semaste
647254721Semaste        if (m_temporary_allocation == LLDB_INVALID_ADDRESS)
648254721Semaste        {
649254721Semaste            dump_stream.Printf("Points to process memory:\n");
650254721Semaste        }
651254721Semaste        else
652254721Semaste        {
653254721Semaste            dump_stream.Printf("Temporary allocation:\n");
654254721Semaste        }
655254721Semaste
656254721Semaste        if (ptr == LLDB_INVALID_ADDRESS)
657254721Semaste        {
658254721Semaste            dump_stream.Printf("  <could not be be found>\n");
659254721Semaste        }
660254721Semaste        else
661254721Semaste        {
662254721Semaste            DataBufferHeap data (m_temporary_allocation_size, 0);
663254721Semaste
664254721Semaste            map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err);
665254721Semaste
666254721Semaste            if (!err.Success())
667254721Semaste            {
668254721Semaste                dump_stream.Printf("  <could not be read>\n");
669254721Semaste            }
670254721Semaste            else
671254721Semaste            {
672254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
673254721Semaste
674254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
675254721Semaste
676254721Semaste                dump_stream.PutChar('\n');
677254721Semaste            }
678254721Semaste        }
679254721Semaste
680254721Semaste        log->PutCString(dump_stream.GetData());
681254721Semaste    }
682254721Semaste
683254721Semaste    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
684254721Semaste    {
685254721Semaste        if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
686254721Semaste        {
687254721Semaste            Error free_error;
688254721Semaste
689254721Semaste            map.Free(m_temporary_allocation, free_error);
690254721Semaste
691254721Semaste            m_temporary_allocation = LLDB_INVALID_ADDRESS;
692254721Semaste            m_temporary_allocation_size = 0;
693254721Semaste        }
694254721Semaste
695254721Semaste    }
696254721Semasteprivate:
697254721Semaste    lldb::VariableSP    m_variable_sp;
698254721Semaste    bool                m_is_reference;
699254721Semaste    lldb::addr_t        m_temporary_allocation;
700254721Semaste    size_t              m_temporary_allocation_size;
701254721Semaste};
702254721Semaste
703254721Semasteuint32_t
704254721SemasteMaterializer::AddVariable (lldb::VariableSP &variable_sp, Error &err)
705254721Semaste{
706254721Semaste    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
707254721Semaste    iter->reset (new EntityVariable (variable_sp));
708254721Semaste    uint32_t ret = AddStructMember(**iter);
709254721Semaste    (*iter)->SetOffset(ret);
710254721Semaste    return ret;
711254721Semaste}
712254721Semaste
713254721Semasteclass EntityResultVariable : public Materializer::Entity
714254721Semaste{
715254721Semastepublic:
716254721Semaste    EntityResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory) :
717254721Semaste        Entity(),
718254721Semaste        m_type(type),
719254721Semaste        m_is_program_reference(is_program_reference),
720254721Semaste        m_keep_in_memory(keep_in_memory),
721254721Semaste        m_temporary_allocation(LLDB_INVALID_ADDRESS),
722254721Semaste        m_temporary_allocation_size(0)
723254721Semaste    {
724254721Semaste        // Hard-coding to maximum size of a pointer since all results are materialized by reference
725254721Semaste        m_size = 8;
726254721Semaste        m_alignment = 8;
727254721Semaste    }
728254721Semaste
729254721Semaste    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
730254721Semaste    {
731254721Semaste        if (!m_is_program_reference)
732254721Semaste        {
733254721Semaste            if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
734254721Semaste            {
735254721Semaste                err.SetErrorString("Trying to create a temporary region for the result but one exists");
736254721Semaste                return;
737254721Semaste            }
738254721Semaste
739254721Semaste            const lldb::addr_t load_addr = process_address + m_offset;
740254721Semaste
741254721Semaste            size_t byte_size = m_type.GetByteSize();
742254721Semaste            size_t bit_align = m_type.GetTypeBitAlign();
743254721Semaste            size_t byte_align = (bit_align + 7) / 8;
744254721Semaste
745254721Semaste            Error alloc_error;
746254721Semaste
747254721Semaste            m_temporary_allocation = map.Malloc(byte_size, byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
748254721Semaste            m_temporary_allocation_size = byte_size;
749254721Semaste
750254721Semaste            if (!alloc_error.Success())
751254721Semaste            {
752254721Semaste                err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString());
753254721Semaste                return;
754254721Semaste            }
755254721Semaste
756254721Semaste            Error pointer_write_error;
757254721Semaste
758254721Semaste            map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error);
759254721Semaste
760254721Semaste            if (!pointer_write_error.Success())
761254721Semaste            {
762254721Semaste                err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString());
763254721Semaste            }
764254721Semaste        }
765254721Semaste    }
766254721Semaste
767254721Semaste    void Dematerialize (lldb::StackFrameSP &frame_sp,
768254721Semaste                        IRMemoryMap &map,
769254721Semaste                        lldb::addr_t process_address,
770254721Semaste                        lldb::addr_t frame_top,
771254721Semaste                        lldb::addr_t frame_bottom,
772254721Semaste                        Error &err)
773254721Semaste    {
774254721Semaste        err.SetErrorString("Tried to detmaterialize a result variable with the normal Dematerialize method");
775254721Semaste    }
776254721Semaste
777254721Semaste    void Dematerialize (lldb::ClangExpressionVariableSP &result_variable_sp,
778254721Semaste                        lldb::StackFrameSP &frame_sp,
779254721Semaste                        IRMemoryMap &map,
780254721Semaste                        lldb::addr_t process_address,
781254721Semaste                        lldb::addr_t frame_top,
782254721Semaste                        lldb::addr_t frame_bottom,
783254721Semaste                        Error &err)
784254721Semaste    {
785254721Semaste        err.Clear();
786254721Semaste
787254721Semaste        ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
788254721Semaste
789254721Semaste        if (!exe_scope)
790254721Semaste        {
791254721Semaste            err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope");
792254721Semaste            return;
793254721Semaste        }
794254721Semaste
795254721Semaste        lldb::addr_t address;
796254721Semaste        Error read_error;
797254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
798254721Semaste
799254721Semaste        map.ReadPointerFromMemory (&address, load_addr, read_error);
800254721Semaste
801254721Semaste        if (!read_error.Success())
802254721Semaste        {
803254721Semaste            err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address");
804254721Semaste            return;
805254721Semaste        }
806254721Semaste
807254721Semaste        lldb::TargetSP target_sp = exe_scope->CalculateTarget();
808254721Semaste
809254721Semaste        if (!target_sp)
810254721Semaste        {
811254721Semaste            err.SetErrorString("Couldn't dematerialize a result variable: no target");
812254721Semaste            return;
813254721Semaste        }
814254721Semaste
815254721Semaste        ConstString name = target_sp->GetPersistentVariables().GetNextPersistentVariableName();
816254721Semaste
817254721Semaste        lldb::ClangExpressionVariableSP ret;
818254721Semaste
819254721Semaste        ret = target_sp->GetPersistentVariables().CreateVariable(exe_scope,
820254721Semaste                                                                 name,
821254721Semaste                                                                 m_type,
822254721Semaste                                                                 map.GetByteOrder(),
823254721Semaste                                                                 map.GetAddressByteSize());
824254721Semaste
825254721Semaste        if (!ret)
826254721Semaste        {
827254721Semaste            err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString());
828254721Semaste            return;
829254721Semaste        }
830254721Semaste
831254721Semaste        lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
832254721Semaste
833254721Semaste        bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top));
834254721Semaste
835254721Semaste        if (can_persist && m_keep_in_memory)
836254721Semaste        {
837254721Semaste            ret->m_live_sp = ValueObjectConstResult::Create(exe_scope,
838254721Semaste                                                            m_type,
839254721Semaste                                                            name,
840254721Semaste                                                            address,
841254721Semaste                                                            eAddressTypeLoad,
842254721Semaste                                                            ret->GetByteSize());
843254721Semaste        }
844254721Semaste
845254721Semaste        ret->ValueUpdated();
846254721Semaste
847254721Semaste        const size_t pvar_byte_size = ret->GetByteSize();
848254721Semaste        uint8_t *pvar_data = ret->GetValueBytes();
849254721Semaste
850254721Semaste        map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
851254721Semaste
852254721Semaste        if (!read_error.Success())
853254721Semaste        {
854254721Semaste            err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory");
855254721Semaste            return;
856254721Semaste        }
857254721Semaste
858254721Semaste        result_variable_sp = ret;
859254721Semaste
860254721Semaste        if (!can_persist || !m_keep_in_memory)
861254721Semaste        {
862254721Semaste            ret->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
863254721Semaste
864254721Semaste            if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
865254721Semaste            {
866254721Semaste                Error free_error;
867254721Semaste                map.Free(m_temporary_allocation, free_error);
868254721Semaste            }
869254721Semaste        }
870254721Semaste        else
871254721Semaste        {
872254721Semaste            ret->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
873254721Semaste        }
874254721Semaste
875254721Semaste        m_temporary_allocation = LLDB_INVALID_ADDRESS;
876254721Semaste        m_temporary_allocation_size = 0;
877254721Semaste    }
878254721Semaste
879254721Semaste    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
880254721Semaste    {
881254721Semaste        StreamString dump_stream;
882254721Semaste
883254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
884254721Semaste
885254721Semaste        dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
886254721Semaste
887254721Semaste        Error err;
888254721Semaste
889254721Semaste        lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
890254721Semaste
891254721Semaste        {
892254721Semaste            dump_stream.Printf("Pointer:\n");
893254721Semaste
894254721Semaste            DataBufferHeap data (m_size, 0);
895254721Semaste
896254721Semaste            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
897254721Semaste
898254721Semaste            if (!err.Success())
899254721Semaste            {
900254721Semaste                dump_stream.Printf("  <could not be read>\n");
901254721Semaste            }
902254721Semaste            else
903254721Semaste            {
904254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
905254721Semaste
906254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
907254721Semaste
908254721Semaste                lldb::offset_t offset;
909254721Semaste
910254721Semaste                ptr = extractor.GetPointer(&offset);
911254721Semaste
912254721Semaste                dump_stream.PutChar('\n');
913254721Semaste            }
914254721Semaste        }
915254721Semaste
916254721Semaste        if (m_temporary_allocation == LLDB_INVALID_ADDRESS)
917254721Semaste        {
918254721Semaste            dump_stream.Printf("Points to process memory:\n");
919254721Semaste        }
920254721Semaste        else
921254721Semaste        {
922254721Semaste            dump_stream.Printf("Temporary allocation:\n");
923254721Semaste        }
924254721Semaste
925254721Semaste        if (ptr == LLDB_INVALID_ADDRESS)
926254721Semaste        {
927254721Semaste            dump_stream.Printf("  <could not be be found>\n");
928254721Semaste        }
929254721Semaste        else
930254721Semaste        {
931254721Semaste            DataBufferHeap data (m_temporary_allocation_size, 0);
932254721Semaste
933254721Semaste            map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err);
934254721Semaste
935254721Semaste            if (!err.Success())
936254721Semaste            {
937254721Semaste                dump_stream.Printf("  <could not be read>\n");
938254721Semaste            }
939254721Semaste            else
940254721Semaste            {
941254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
942254721Semaste
943254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
944254721Semaste
945254721Semaste                dump_stream.PutChar('\n');
946254721Semaste            }
947254721Semaste        }
948254721Semaste
949254721Semaste        log->PutCString(dump_stream.GetData());
950254721Semaste    }
951254721Semaste
952254721Semaste    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
953254721Semaste    {
954254721Semaste        if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS)
955254721Semaste        {
956254721Semaste            Error free_error;
957254721Semaste
958254721Semaste            map.Free(m_temporary_allocation, free_error);
959254721Semaste        }
960254721Semaste
961254721Semaste        m_temporary_allocation = LLDB_INVALID_ADDRESS;
962254721Semaste        m_temporary_allocation_size = 0;
963254721Semaste    }
964254721Semasteprivate:
965254721Semaste    TypeFromUser    m_type;
966254721Semaste    bool            m_is_program_reference;
967254721Semaste    bool            m_keep_in_memory;
968254721Semaste
969254721Semaste    lldb::addr_t    m_temporary_allocation;
970254721Semaste    size_t          m_temporary_allocation_size;
971254721Semaste};
972254721Semaste
973254721Semasteuint32_t
974254721SemasteMaterializer::AddResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory, Error &err)
975254721Semaste{
976254721Semaste    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
977254721Semaste    iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory));
978254721Semaste    uint32_t ret = AddStructMember(**iter);
979254721Semaste    (*iter)->SetOffset(ret);
980254721Semaste    m_result_entity = iter->get();
981254721Semaste    return ret;
982254721Semaste}
983254721Semaste
984254721Semasteclass EntitySymbol : public Materializer::Entity
985254721Semaste{
986254721Semastepublic:
987254721Semaste    EntitySymbol (const Symbol &symbol) :
988254721Semaste        Entity(),
989254721Semaste        m_symbol(symbol)
990254721Semaste    {
991254721Semaste        // Hard-coding to maximum size of a symbol
992254721Semaste        m_size = 8;
993254721Semaste        m_alignment = 8;
994254721Semaste    }
995254721Semaste
996254721Semaste    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
997254721Semaste    {
998254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
999254721Semaste
1000254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1001254721Semaste
1002254721Semaste        if (log)
1003254721Semaste        {
1004254721Semaste            log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 ", m_symbol = %s]",
1005254721Semaste                        (uint64_t)load_addr,
1006254721Semaste                        m_symbol.GetName().AsCString());
1007254721Semaste        }
1008254721Semaste
1009254721Semaste        Address &sym_address = m_symbol.GetAddress();
1010254721Semaste
1011254721Semaste        ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
1012254721Semaste
1013254721Semaste        lldb::TargetSP target_sp;
1014254721Semaste
1015254721Semaste        if (exe_scope)
1016254721Semaste            target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
1017254721Semaste
1018254721Semaste        if (!target_sp)
1019254721Semaste        {
1020254721Semaste            err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString());
1021254721Semaste            return;
1022254721Semaste        }
1023254721Semaste
1024254721Semaste        lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
1025254721Semaste
1026254721Semaste        if (resolved_address == LLDB_INVALID_ADDRESS)
1027254721Semaste            resolved_address = sym_address.GetFileAddress();
1028254721Semaste
1029254721Semaste        Error pointer_write_error;
1030254721Semaste
1031254721Semaste        map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
1032254721Semaste
1033254721Semaste        if (!pointer_write_error.Success())
1034254721Semaste        {
1035254721Semaste            err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
1036254721Semaste            return;
1037254721Semaste        }
1038254721Semaste    }
1039254721Semaste
1040254721Semaste    void Dematerialize (lldb::StackFrameSP &frame_sp,
1041254721Semaste                        IRMemoryMap &map,
1042254721Semaste                        lldb::addr_t process_address,
1043254721Semaste                        lldb::addr_t frame_top,
1044254721Semaste                        lldb::addr_t frame_bottom,
1045254721Semaste                        Error &err)
1046254721Semaste    {
1047254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1048254721Semaste
1049254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1050254721Semaste
1051254721Semaste        if (log)
1052254721Semaste        {
1053254721Semaste            log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 ", m_symbol = %s]",
1054254721Semaste                        (uint64_t)load_addr,
1055254721Semaste                        m_symbol.GetName().AsCString());
1056254721Semaste        }
1057254721Semaste
1058254721Semaste        // no work needs to be done
1059254721Semaste    }
1060254721Semaste
1061254721Semaste    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
1062254721Semaste    {
1063254721Semaste        StreamString dump_stream;
1064254721Semaste
1065254721Semaste        Error err;
1066254721Semaste
1067254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1068254721Semaste
1069254721Semaste        dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, m_symbol.GetName().AsCString());
1070254721Semaste
1071254721Semaste        {
1072254721Semaste            dump_stream.Printf("Pointer:\n");
1073254721Semaste
1074254721Semaste            DataBufferHeap data (m_size, 0);
1075254721Semaste
1076254721Semaste            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1077254721Semaste
1078254721Semaste            if (!err.Success())
1079254721Semaste            {
1080254721Semaste                dump_stream.Printf("  <could not be read>\n");
1081254721Semaste            }
1082254721Semaste            else
1083254721Semaste            {
1084254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
1085254721Semaste
1086254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
1087254721Semaste
1088254721Semaste                dump_stream.PutChar('\n');
1089254721Semaste            }
1090254721Semaste        }
1091254721Semaste
1092254721Semaste        log->PutCString(dump_stream.GetData());
1093254721Semaste    }
1094254721Semaste
1095254721Semaste    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
1096254721Semaste    {
1097254721Semaste    }
1098254721Semasteprivate:
1099254721Semaste    Symbol m_symbol;
1100254721Semaste};
1101254721Semaste
1102254721Semasteuint32_t
1103254721SemasteMaterializer::AddSymbol (const Symbol &symbol_sp, Error &err)
1104254721Semaste{
1105254721Semaste    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1106254721Semaste    iter->reset (new EntitySymbol (symbol_sp));
1107254721Semaste    uint32_t ret = AddStructMember(**iter);
1108254721Semaste    (*iter)->SetOffset(ret);
1109254721Semaste    return ret;
1110254721Semaste}
1111254721Semaste
1112254721Semasteclass EntityRegister : public Materializer::Entity
1113254721Semaste{
1114254721Semastepublic:
1115254721Semaste    EntityRegister (const RegisterInfo &register_info) :
1116254721Semaste        Entity(),
1117254721Semaste        m_register_info(register_info)
1118254721Semaste    {
1119254721Semaste        // Hard-coding alignment conservatively
1120254721Semaste        m_size = m_register_info.byte_size;
1121254721Semaste        m_alignment = m_register_info.byte_size;
1122254721Semaste    }
1123254721Semaste
1124254721Semaste    void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
1125254721Semaste    {
1126254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1127254721Semaste
1128254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1129254721Semaste
1130254721Semaste        if (log)
1131254721Semaste        {
1132254721Semaste            log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 ", m_register_info = %s]",
1133254721Semaste                        (uint64_t)load_addr,
1134254721Semaste                        m_register_info.name);
1135254721Semaste        }
1136254721Semaste
1137254721Semaste        RegisterValue reg_value;
1138254721Semaste
1139254721Semaste        if (!frame_sp.get())
1140254721Semaste        {
1141254721Semaste            err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name);
1142254721Semaste            return;
1143254721Semaste        }
1144254721Semaste
1145254721Semaste        lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1146254721Semaste
1147254721Semaste        if (!reg_context_sp->ReadRegister(&m_register_info, reg_value))
1148254721Semaste        {
1149254721Semaste            err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name);
1150254721Semaste            return;
1151254721Semaste        }
1152254721Semaste
1153254721Semaste        DataExtractor register_data;
1154254721Semaste
1155254721Semaste        if (!reg_value.GetData(register_data))
1156254721Semaste        {
1157254721Semaste            err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name);
1158254721Semaste            return;
1159254721Semaste        }
1160254721Semaste
1161254721Semaste        if (register_data.GetByteSize() != m_register_info.byte_size)
1162254721Semaste        {
1163254721Semaste            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);
1164254721Semaste            return;
1165254721Semaste        }
1166254721Semaste
1167254721Semaste        m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize()));
1168254721Semaste
1169254721Semaste        Error write_error;
1170254721Semaste
1171254721Semaste        map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error);
1172254721Semaste
1173254721Semaste        if (!write_error.Success())
1174254721Semaste        {
1175254721Semaste            err.SetErrorStringWithFormat("couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString());
1176254721Semaste            return;
1177254721Semaste        }
1178254721Semaste    }
1179254721Semaste
1180254721Semaste    void Dematerialize (lldb::StackFrameSP &frame_sp,
1181254721Semaste                        IRMemoryMap &map,
1182254721Semaste                        lldb::addr_t process_address,
1183254721Semaste                        lldb::addr_t frame_top,
1184254721Semaste                        lldb::addr_t frame_bottom,
1185254721Semaste                        Error &err)
1186254721Semaste    {
1187254721Semaste        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
1188254721Semaste
1189254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1190254721Semaste
1191254721Semaste        if (log)
1192254721Semaste        {
1193254721Semaste            log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]",
1194254721Semaste                        (uint64_t)load_addr,
1195254721Semaste                        m_register_info.name);
1196254721Semaste        }
1197254721Semaste
1198254721Semaste        Error extract_error;
1199254721Semaste
1200254721Semaste        DataExtractor register_data;
1201254721Semaste
1202254721Semaste        if (!frame_sp.get())
1203254721Semaste        {
1204254721Semaste            err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name);
1205254721Semaste            return;
1206254721Semaste        }
1207254721Semaste
1208254721Semaste        lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1209254721Semaste
1210254721Semaste        map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error);
1211254721Semaste
1212254721Semaste        if (!extract_error.Success())
1213254721Semaste        {
1214254721Semaste            err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString());
1215254721Semaste            return;
1216254721Semaste        }
1217254721Semaste
1218254721Semaste        if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize()))
1219254721Semaste        {
1220254721Semaste            // No write required, and in particular we avoid errors if the register wasn't writable
1221254721Semaste
1222254721Semaste            m_register_contents.reset();
1223254721Semaste            return;
1224254721Semaste        }
1225254721Semaste
1226254721Semaste        m_register_contents.reset();
1227254721Semaste
1228254721Semaste        RegisterValue register_value (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder());
1229254721Semaste
1230254721Semaste        if (!reg_context_sp->WriteRegister(&m_register_info, register_value))
1231254721Semaste        {
1232254721Semaste            err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name);
1233254721Semaste            return;
1234254721Semaste        }
1235254721Semaste    }
1236254721Semaste
1237254721Semaste    void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
1238254721Semaste    {
1239254721Semaste        StreamString dump_stream;
1240254721Semaste
1241254721Semaste        Error err;
1242254721Semaste
1243254721Semaste        const lldb::addr_t load_addr = process_address + m_offset;
1244254721Semaste
1245254721Semaste
1246254721Semaste        dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, m_register_info.name);
1247254721Semaste
1248254721Semaste        {
1249254721Semaste            dump_stream.Printf("Value:\n");
1250254721Semaste
1251254721Semaste            DataBufferHeap data (m_size, 0);
1252254721Semaste
1253254721Semaste            map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1254254721Semaste
1255254721Semaste            if (!err.Success())
1256254721Semaste            {
1257254721Semaste                dump_stream.Printf("  <could not be read>\n");
1258254721Semaste            }
1259254721Semaste            else
1260254721Semaste            {
1261254721Semaste                DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize());
1262254721Semaste
1263254721Semaste                extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr);
1264254721Semaste
1265254721Semaste                dump_stream.PutChar('\n');
1266254721Semaste            }
1267254721Semaste        }
1268254721Semaste
1269254721Semaste        log->PutCString(dump_stream.GetData());
1270254721Semaste    }
1271254721Semaste
1272254721Semaste    void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
1273254721Semaste    {
1274254721Semaste    }
1275254721Semasteprivate:
1276254721Semaste    RegisterInfo m_register_info;
1277254721Semaste    lldb::DataBufferSP m_register_contents;
1278254721Semaste};
1279254721Semaste
1280254721Semasteuint32_t
1281254721SemasteMaterializer::AddRegister (const RegisterInfo &register_info, Error &err)
1282254721Semaste{
1283254721Semaste    EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1284254721Semaste    iter->reset (new EntityRegister (register_info));
1285254721Semaste    uint32_t ret = AddStructMember(**iter);
1286254721Semaste    (*iter)->SetOffset(ret);
1287254721Semaste    return ret;
1288254721Semaste}
1289254721Semaste
1290254721SemasteMaterializer::Materializer () :
1291254721Semaste    m_dematerializer_wp(),
1292254721Semaste    m_result_entity(NULL),
1293254721Semaste    m_current_offset(0),
1294254721Semaste    m_struct_alignment(8)
1295254721Semaste{
1296254721Semaste}
1297254721Semaste
1298254721SemasteMaterializer::~Materializer ()
1299254721Semaste{
1300254721Semaste    DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1301254721Semaste
1302254721Semaste    if (dematerializer_sp)
1303254721Semaste        dematerializer_sp->Wipe();
1304254721Semaste}
1305254721Semaste
1306254721SemasteMaterializer::DematerializerSP
1307254721SemasteMaterializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error)
1308254721Semaste{
1309254721Semaste    ExecutionContextScope *exe_scope = frame_sp.get();
1310254721Semaste
1311254721Semaste    if (!exe_scope)
1312254721Semaste        exe_scope = map.GetBestExecutionContextScope();
1313254721Semaste
1314254721Semaste    DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1315254721Semaste
1316254721Semaste    if (dematerializer_sp)
1317254721Semaste    {
1318254721Semaste        error.SetErrorToGenericError();
1319254721Semaste        error.SetErrorString("Couldn't materialize: already materialized");
1320254721Semaste    }
1321254721Semaste
1322254721Semaste    DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address));
1323254721Semaste
1324254721Semaste    if (!exe_scope)
1325254721Semaste    {
1326254721Semaste        error.SetErrorToGenericError();
1327254721Semaste        error.SetErrorString("Couldn't materialize: target doesn't exist");
1328254721Semaste    }
1329254721Semaste
1330254721Semaste    for (EntityUP &entity_up : m_entities)
1331254721Semaste    {
1332254721Semaste        entity_up->Materialize(frame_sp, map, process_address, error);
1333254721Semaste
1334254721Semaste        if (!error.Success())
1335254721Semaste            return DematerializerSP();
1336254721Semaste    }
1337254721Semaste
1338254721Semaste    if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
1339254721Semaste    {
1340254721Semaste        log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", frame_sp.get(), process_address);
1341254721Semaste        for (EntityUP &entity_up : m_entities)
1342254721Semaste            entity_up->DumpToLog(map, process_address, log);
1343254721Semaste    }
1344254721Semaste
1345254721Semaste    m_dematerializer_wp = ret;
1346254721Semaste
1347254721Semaste    return ret;
1348254721Semaste}
1349254721Semaste
1350254721Semastevoid
1351254721SemasteMaterializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_bottom, lldb::addr_t frame_top)
1352254721Semaste{
1353254721Semaste    lldb::StackFrameSP frame_sp;
1354254721Semaste
1355254721Semaste    lldb::ThreadSP thread_sp = m_thread_wp.lock();
1356254721Semaste    if (thread_sp)
1357254721Semaste        frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
1358254721Semaste
1359254721Semaste    ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope();
1360254721Semaste
1361254721Semaste    if (!IsValid())
1362254721Semaste    {
1363254721Semaste        error.SetErrorToGenericError();
1364254721Semaste        error.SetErrorString("Couldn't dematerialize: invalid dematerializer");
1365254721Semaste    }
1366254721Semaste
1367254721Semaste    if (!exe_scope)
1368254721Semaste    {
1369254721Semaste        error.SetErrorToGenericError();
1370254721Semaste        error.SetErrorString("Couldn't dematerialize: target is gone");
1371254721Semaste    }
1372254721Semaste    else
1373254721Semaste    {
1374254721Semaste        if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
1375254721Semaste        {
1376254721Semaste            log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", frame_sp.get(), m_process_address);
1377254721Semaste            for (EntityUP &entity_up : m_materializer->m_entities)
1378254721Semaste                entity_up->DumpToLog(*m_map, m_process_address, log);
1379254721Semaste        }
1380254721Semaste
1381254721Semaste        for (EntityUP &entity_up : m_materializer->m_entities)
1382254721Semaste        {
1383254721Semaste            if (entity_up.get() == m_materializer->m_result_entity)
1384254721Semaste            {
1385254721Semaste                static_cast<EntityResultVariable*>(m_materializer->m_result_entity)->Dematerialize (result_sp, frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
1386254721Semaste            }
1387254721Semaste            else
1388254721Semaste            {
1389254721Semaste                entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
1390254721Semaste            }
1391254721Semaste
1392254721Semaste            if (!error.Success())
1393254721Semaste                break;
1394254721Semaste        }
1395254721Semaste    }
1396254721Semaste
1397254721Semaste    Wipe();
1398254721Semaste}
1399254721Semaste
1400254721Semastevoid
1401254721SemasteMaterializer::Dematerializer::Wipe ()
1402254721Semaste{
1403254721Semaste    if (!IsValid())
1404254721Semaste        return;
1405254721Semaste
1406254721Semaste    for (EntityUP &entity_up : m_materializer->m_entities)
1407254721Semaste    {
1408254721Semaste        entity_up->Wipe (*m_map, m_process_address);
1409254721Semaste    }
1410254721Semaste
1411254721Semaste    m_materializer = NULL;
1412254721Semaste    m_map = NULL;
1413254721Semaste    m_process_address = LLDB_INVALID_ADDRESS;
1414254721Semaste}
1415