1254721Semaste//===-- IRMemoryMap.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/DataBufferHeap.h"
11254721Semaste#include "lldb/Core/DataExtractor.h"
12254721Semaste#include "lldb/Core/Error.h"
13254721Semaste#include "lldb/Core/Log.h"
14254721Semaste#include "lldb/Core/Scalar.h"
15254721Semaste#include "lldb/Expression/IRMemoryMap.h"
16254721Semaste#include "lldb/Target/Process.h"
17254721Semaste#include "lldb/Target/Target.h"
18254721Semaste
19254721Semasteusing namespace lldb_private;
20254721Semaste
21254721SemasteIRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
22254721Semaste    m_target_wp(target_sp)
23254721Semaste{
24254721Semaste    if (target_sp)
25254721Semaste        m_process_wp = target_sp->GetProcessSP();
26254721Semaste}
27254721Semaste
28254721SemasteIRMemoryMap::~IRMemoryMap ()
29254721Semaste{
30254721Semaste    lldb::ProcessSP process_sp = m_process_wp.lock();
31254721Semaste
32254721Semaste    if (process_sp)
33254721Semaste    {
34254721Semaste        AllocationMap::iterator iter;
35254721Semaste
36254721Semaste        Error err;
37254721Semaste
38254721Semaste        while ((iter = m_allocations.begin()) != m_allocations.end())
39254721Semaste        {
40254721Semaste            err.Clear();
41254721Semaste            if (iter->second.m_leak)
42254721Semaste                m_allocations.erase(iter);
43254721Semaste            else
44254721Semaste                Free(iter->first, err);
45254721Semaste        }
46254721Semaste    }
47254721Semaste}
48254721Semaste
49254721Semastelldb::addr_t
50254721SemasteIRMemoryMap::FindSpace (size_t size)
51254721Semaste{
52254721Semaste    lldb::TargetSP target_sp = m_target_wp.lock();
53254721Semaste    lldb::ProcessSP process_sp = m_process_wp.lock();
54254721Semaste
55254721Semaste    lldb::addr_t ret = LLDB_INVALID_ADDRESS;
56254721Semaste
57254721Semaste    if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
58254721Semaste    {
59254721Semaste        Error alloc_error;
60254721Semaste
61254721Semaste        ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
62254721Semaste
63254721Semaste        if (!alloc_error.Success())
64254721Semaste            return LLDB_INVALID_ADDRESS;
65254721Semaste        else
66254721Semaste            return ret;
67254721Semaste    }
68254721Semaste
69254721Semaste    for (int iterations = 0; iterations < 16; ++iterations)
70254721Semaste    {
71254721Semaste        lldb::addr_t candidate = LLDB_INVALID_ADDRESS;
72254721Semaste
73254721Semaste        switch (target_sp->GetArchitecture().GetAddressByteSize())
74254721Semaste        {
75254721Semaste        case 4:
76254721Semaste            {
77263363Semaste                uint32_t random_data = rand();
78254721Semaste                candidate = random_data;
79254721Semaste                candidate &= ~0xfffull;
80254721Semaste                break;
81254721Semaste            }
82254721Semaste        case 8:
83254721Semaste            {
84263363Semaste                uint32_t random_low = rand();
85263363Semaste                uint32_t random_high = rand();
86254721Semaste                candidate = random_high;
87254721Semaste                candidate <<= 32ull;
88254721Semaste                candidate |= random_low;
89254721Semaste                candidate &= ~0xfffull;
90254721Semaste                break;
91254721Semaste            }
92254721Semaste        }
93254721Semaste
94254721Semaste        if (IntersectsAllocation(candidate, size))
95254721Semaste            continue;
96254721Semaste
97254721Semaste        ret = candidate;
98254721Semaste
99254721Semaste        return ret;
100254721Semaste    }
101254721Semaste
102254721Semaste    return ret;
103254721Semaste}
104254721Semaste
105254721SemasteIRMemoryMap::AllocationMap::iterator
106254721SemasteIRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
107254721Semaste{
108254721Semaste    if (addr == LLDB_INVALID_ADDRESS)
109254721Semaste        return m_allocations.end();
110254721Semaste
111254721Semaste    AllocationMap::iterator iter = m_allocations.lower_bound (addr);
112254721Semaste
113254721Semaste    if (iter == m_allocations.end() ||
114254721Semaste        iter->first > addr)
115254721Semaste    {
116254721Semaste        if (iter == m_allocations.begin())
117254721Semaste            return m_allocations.end();
118254721Semaste        iter--;
119254721Semaste    }
120254721Semaste
121254721Semaste    if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
122254721Semaste        return iter;
123254721Semaste
124254721Semaste    return m_allocations.end();
125254721Semaste}
126254721Semaste
127254721Semastebool
128254721SemasteIRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size)
129254721Semaste{
130254721Semaste    if (addr == LLDB_INVALID_ADDRESS)
131254721Semaste        return false;
132254721Semaste
133254721Semaste    AllocationMap::iterator iter = m_allocations.lower_bound (addr);
134254721Semaste
135254721Semaste    if (iter == m_allocations.end() ||
136254721Semaste        iter->first > addr)
137254721Semaste    {
138254721Semaste        if (iter == m_allocations.begin())
139254721Semaste            return false;
140254721Semaste
141254721Semaste        iter--;
142254721Semaste    }
143254721Semaste
144254721Semaste    while (iter != m_allocations.end() && iter->second.m_process_alloc < addr + size)
145254721Semaste    {
146254721Semaste        if (iter->second.m_process_start + iter->second.m_size > addr)
147254721Semaste            return true;
148254721Semaste
149254721Semaste        ++iter;
150254721Semaste    }
151254721Semaste
152254721Semaste    return false;
153254721Semaste}
154254721Semaste
155254721Semastelldb::ByteOrder
156254721SemasteIRMemoryMap::GetByteOrder()
157254721Semaste{
158254721Semaste    lldb::ProcessSP process_sp = m_process_wp.lock();
159254721Semaste
160254721Semaste    if (process_sp)
161254721Semaste        return process_sp->GetByteOrder();
162254721Semaste
163254721Semaste    lldb::TargetSP target_sp = m_target_wp.lock();
164254721Semaste
165254721Semaste    if (target_sp)
166254721Semaste        return target_sp->GetArchitecture().GetByteOrder();
167254721Semaste
168254721Semaste    return lldb::eByteOrderInvalid;
169254721Semaste}
170254721Semaste
171254721Semasteuint32_t
172254721SemasteIRMemoryMap::GetAddressByteSize()
173254721Semaste{
174254721Semaste    lldb::ProcessSP process_sp = m_process_wp.lock();
175254721Semaste
176254721Semaste    if (process_sp)
177254721Semaste        return process_sp->GetAddressByteSize();
178254721Semaste
179254721Semaste    lldb::TargetSP target_sp = m_target_wp.lock();
180254721Semaste
181254721Semaste    if (target_sp)
182254721Semaste        return target_sp->GetArchitecture().GetAddressByteSize();
183254721Semaste
184254721Semaste    return UINT32_MAX;
185254721Semaste}
186254721Semaste
187254721SemasteExecutionContextScope *
188254721SemasteIRMemoryMap::GetBestExecutionContextScope()
189254721Semaste{
190254721Semaste    lldb::ProcessSP process_sp = m_process_wp.lock();
191254721Semaste
192254721Semaste    if (process_sp)
193254721Semaste        return process_sp.get();
194254721Semaste
195254721Semaste    lldb::TargetSP target_sp = m_target_wp.lock();
196254721Semaste
197254721Semaste    if (target_sp)
198254721Semaste        return target_sp.get();
199254721Semaste
200254721Semaste    return NULL;
201254721Semaste}
202254721Semaste
203254721SemasteIRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
204254721Semaste                                     lldb::addr_t process_start,
205254721Semaste                                     size_t size,
206254721Semaste                                     uint32_t permissions,
207254721Semaste                                     uint8_t alignment,
208254721Semaste                                     AllocationPolicy policy) :
209254721Semaste    m_process_alloc (process_alloc),
210254721Semaste    m_process_start (process_start),
211254721Semaste    m_size (size),
212254721Semaste    m_permissions (permissions),
213254721Semaste    m_alignment (alignment),
214254721Semaste    m_policy (policy),
215254721Semaste    m_leak (false)
216254721Semaste{
217254721Semaste    switch (policy)
218254721Semaste    {
219254721Semaste        default:
220254721Semaste            assert (0 && "We cannot reach this!");
221254721Semaste        case eAllocationPolicyHostOnly:
222254721Semaste            m_data.SetByteSize(size);
223254721Semaste            memset(m_data.GetBytes(), 0, size);
224254721Semaste            break;
225254721Semaste        case eAllocationPolicyProcessOnly:
226254721Semaste            break;
227254721Semaste        case eAllocationPolicyMirror:
228254721Semaste            m_data.SetByteSize(size);
229254721Semaste            memset(m_data.GetBytes(), 0, size);
230254721Semaste            break;
231254721Semaste    }
232254721Semaste}
233254721Semaste
234254721Semastelldb::addr_t
235254721SemasteIRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
236254721Semaste{
237254721Semaste    error.Clear();
238254721Semaste
239254721Semaste    lldb::ProcessSP process_sp;
240254721Semaste    lldb::addr_t    allocation_address  = LLDB_INVALID_ADDRESS;
241254721Semaste    lldb::addr_t    aligned_address     = LLDB_INVALID_ADDRESS;
242254721Semaste
243254721Semaste    size_t          alignment_mask = alignment - 1;
244254721Semaste    size_t          allocation_size;
245254721Semaste
246254721Semaste    if (size == 0)
247254721Semaste        allocation_size = alignment;
248254721Semaste    else
249254721Semaste        allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
250254721Semaste
251254721Semaste    switch (policy)
252254721Semaste    {
253254721Semaste    default:
254254721Semaste        error.SetErrorToGenericError();
255254721Semaste        error.SetErrorString("Couldn't malloc: invalid allocation policy");
256254721Semaste        return LLDB_INVALID_ADDRESS;
257254721Semaste    case eAllocationPolicyHostOnly:
258254721Semaste        allocation_address = FindSpace(allocation_size);
259254721Semaste        if (allocation_address == LLDB_INVALID_ADDRESS)
260254721Semaste        {
261254721Semaste            error.SetErrorToGenericError();
262254721Semaste            error.SetErrorString("Couldn't malloc: address space is full");
263254721Semaste            return LLDB_INVALID_ADDRESS;
264254721Semaste        }
265254721Semaste        break;
266254721Semaste    case eAllocationPolicyMirror:
267254721Semaste        process_sp = m_process_wp.lock();
268254721Semaste        if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
269254721Semaste        {
270254721Semaste            allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
271254721Semaste            if (!error.Success())
272254721Semaste                return LLDB_INVALID_ADDRESS;
273254721Semaste        }
274254721Semaste        else
275254721Semaste        {
276254721Semaste            policy = eAllocationPolicyHostOnly;
277254721Semaste            allocation_address = FindSpace(allocation_size);
278254721Semaste            if (allocation_address == LLDB_INVALID_ADDRESS)
279254721Semaste            {
280254721Semaste                error.SetErrorToGenericError();
281254721Semaste                error.SetErrorString("Couldn't malloc: address space is full");
282254721Semaste                return LLDB_INVALID_ADDRESS;
283254721Semaste            }
284254721Semaste        }
285254721Semaste        break;
286254721Semaste    case eAllocationPolicyProcessOnly:
287254721Semaste        process_sp = m_process_wp.lock();
288254721Semaste        if (process_sp)
289254721Semaste        {
290254721Semaste            if (process_sp->CanJIT() && process_sp->IsAlive())
291254721Semaste            {
292254721Semaste                allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
293254721Semaste                if (!error.Success())
294254721Semaste                    return LLDB_INVALID_ADDRESS;
295254721Semaste            }
296254721Semaste            else
297254721Semaste            {
298254721Semaste                error.SetErrorToGenericError();
299254721Semaste                error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
300254721Semaste                return LLDB_INVALID_ADDRESS;
301254721Semaste            }
302254721Semaste        }
303254721Semaste        else
304254721Semaste        {
305254721Semaste            error.SetErrorToGenericError();
306254721Semaste            error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
307254721Semaste            return LLDB_INVALID_ADDRESS;
308254721Semaste        }
309254721Semaste        break;
310254721Semaste    }
311254721Semaste
312254721Semaste
313254721Semaste    lldb::addr_t mask = alignment - 1;
314254721Semaste    aligned_address = (allocation_address + mask) & (~mask);
315254721Semaste
316254721Semaste    m_allocations[aligned_address] = Allocation(allocation_address,
317254721Semaste                                                aligned_address,
318254721Semaste                                                allocation_size,
319254721Semaste                                                permissions,
320254721Semaste                                                alignment,
321254721Semaste                                                policy);
322254721Semaste
323254721Semaste    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
324254721Semaste    {
325254721Semaste        const char * policy_string;
326254721Semaste
327254721Semaste        switch (policy)
328254721Semaste        {
329254721Semaste        default:
330254721Semaste            policy_string = "<invalid policy>";
331254721Semaste            break;
332254721Semaste        case eAllocationPolicyHostOnly:
333254721Semaste            policy_string = "eAllocationPolicyHostOnly";
334254721Semaste            break;
335254721Semaste        case eAllocationPolicyProcessOnly:
336254721Semaste            policy_string = "eAllocationPolicyProcessOnly";
337254721Semaste            break;
338254721Semaste        case eAllocationPolicyMirror:
339254721Semaste            policy_string = "eAllocationPolicyMirror";
340254721Semaste            break;
341254721Semaste        }
342254721Semaste
343254721Semaste        log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
344254721Semaste                    (uint64_t)allocation_size,
345254721Semaste                    (uint64_t)alignment,
346254721Semaste                    (uint64_t)permissions,
347254721Semaste                    policy_string,
348254721Semaste                    aligned_address);
349254721Semaste    }
350254721Semaste
351254721Semaste    return aligned_address;
352254721Semaste}
353254721Semaste
354254721Semastevoid
355254721SemasteIRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
356254721Semaste{
357254721Semaste    error.Clear();
358254721Semaste
359254721Semaste    AllocationMap::iterator iter = m_allocations.find(process_address);
360254721Semaste
361254721Semaste    if (iter == m_allocations.end())
362254721Semaste    {
363254721Semaste        error.SetErrorToGenericError();
364254721Semaste        error.SetErrorString("Couldn't leak: allocation doesn't exist");
365254721Semaste        return;
366254721Semaste    }
367254721Semaste
368254721Semaste    Allocation &allocation = iter->second;
369254721Semaste
370254721Semaste    allocation.m_leak = true;
371254721Semaste}
372254721Semaste
373254721Semastevoid
374254721SemasteIRMemoryMap::Free (lldb::addr_t process_address, Error &error)
375254721Semaste{
376254721Semaste    error.Clear();
377254721Semaste
378254721Semaste    AllocationMap::iterator iter = m_allocations.find(process_address);
379254721Semaste
380254721Semaste    if (iter == m_allocations.end())
381254721Semaste    {
382254721Semaste        error.SetErrorToGenericError();
383254721Semaste        error.SetErrorString("Couldn't free: allocation doesn't exist");
384254721Semaste        return;
385254721Semaste    }
386254721Semaste
387254721Semaste    Allocation &allocation = iter->second;
388254721Semaste
389254721Semaste    switch (allocation.m_policy)
390254721Semaste    {
391254721Semaste    default:
392254721Semaste    case eAllocationPolicyHostOnly:
393254721Semaste        {
394254721Semaste            lldb::ProcessSP process_sp = m_process_wp.lock();
395254721Semaste            if (process_sp)
396254721Semaste            {
397254721Semaste                if (process_sp->CanJIT() && process_sp->IsAlive())
398254721Semaste                    process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
399254721Semaste            }
400254721Semaste
401254721Semaste            break;
402254721Semaste        }
403254721Semaste    case eAllocationPolicyMirror:
404254721Semaste    case eAllocationPolicyProcessOnly:
405254721Semaste        {
406254721Semaste            lldb::ProcessSP process_sp = m_process_wp.lock();
407254721Semaste            if (process_sp)
408254721Semaste                process_sp->DeallocateMemory(allocation.m_process_alloc);
409254721Semaste        }
410254721Semaste    }
411254721Semaste
412254721Semaste    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
413254721Semaste    {
414254721Semaste        log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
415254721Semaste                    (uint64_t)process_address,
416254721Semaste                    iter->second.m_process_start,
417254721Semaste                    iter->second.m_process_start + iter->second.m_size);
418254721Semaste    }
419254721Semaste
420254721Semaste    m_allocations.erase(iter);
421254721Semaste}
422254721Semaste
423254721Semastevoid
424254721SemasteIRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
425254721Semaste{
426254721Semaste    error.Clear();
427254721Semaste
428254721Semaste    AllocationMap::iterator iter = FindAllocation(process_address, size);
429254721Semaste
430254721Semaste    if (iter == m_allocations.end())
431254721Semaste    {
432254721Semaste        lldb::ProcessSP process_sp = m_process_wp.lock();
433254721Semaste
434254721Semaste        if (process_sp)
435254721Semaste        {
436254721Semaste            process_sp->WriteMemory(process_address, bytes, size, error);
437254721Semaste            return;
438254721Semaste        }
439254721Semaste
440254721Semaste        error.SetErrorToGenericError();
441254721Semaste        error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
442254721Semaste        return;
443254721Semaste    }
444254721Semaste
445254721Semaste    Allocation &allocation = iter->second;
446254721Semaste
447254721Semaste    uint64_t offset = process_address - allocation.m_process_start;
448254721Semaste
449254721Semaste    lldb::ProcessSP process_sp;
450254721Semaste
451254721Semaste    switch (allocation.m_policy)
452254721Semaste    {
453254721Semaste    default:
454254721Semaste        error.SetErrorToGenericError();
455254721Semaste        error.SetErrorString("Couldn't write: invalid allocation policy");
456254721Semaste        return;
457254721Semaste    case eAllocationPolicyHostOnly:
458254721Semaste        if (!allocation.m_data.GetByteSize())
459254721Semaste        {
460254721Semaste            error.SetErrorToGenericError();
461254721Semaste            error.SetErrorString("Couldn't write: data buffer is empty");
462254721Semaste            return;
463254721Semaste        }
464254721Semaste        ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
465254721Semaste        break;
466254721Semaste    case eAllocationPolicyMirror:
467254721Semaste        if (!allocation.m_data.GetByteSize())
468254721Semaste        {
469254721Semaste            error.SetErrorToGenericError();
470254721Semaste            error.SetErrorString("Couldn't write: data buffer is empty");
471254721Semaste            return;
472254721Semaste        }
473254721Semaste        ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
474254721Semaste        process_sp = m_process_wp.lock();
475254721Semaste        if (process_sp)
476254721Semaste        {
477254721Semaste            process_sp->WriteMemory(process_address, bytes, size, error);
478254721Semaste            if (!error.Success())
479254721Semaste                return;
480254721Semaste        }
481254721Semaste        break;
482254721Semaste    case eAllocationPolicyProcessOnly:
483254721Semaste        process_sp = m_process_wp.lock();
484254721Semaste        if (process_sp)
485254721Semaste        {
486254721Semaste            process_sp->WriteMemory(process_address, bytes, size, error);
487254721Semaste            if (!error.Success())
488254721Semaste                return;
489254721Semaste        }
490254721Semaste        break;
491254721Semaste    }
492254721Semaste
493254721Semaste    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
494254721Semaste    {
495254721Semaste        log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
496254721Semaste                    (uint64_t)process_address,
497254721Semaste                    (uint64_t)bytes,
498254721Semaste                    (uint64_t)size,
499254721Semaste                    (uint64_t)allocation.m_process_start,
500254721Semaste                    (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
501254721Semaste    }
502254721Semaste}
503254721Semaste
504254721Semastevoid
505254721SemasteIRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
506254721Semaste{
507254721Semaste    error.Clear();
508254721Semaste
509254721Semaste    if (size == UINT32_MAX)
510254721Semaste        size = scalar.GetByteSize();
511254721Semaste
512254721Semaste    if (size > 0)
513254721Semaste    {
514254721Semaste        uint8_t buf[32];
515254721Semaste        const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
516254721Semaste        if (mem_size > 0)
517254721Semaste        {
518254721Semaste            return WriteMemory(process_address, buf, mem_size, error);
519254721Semaste        }
520254721Semaste        else
521254721Semaste        {
522254721Semaste            error.SetErrorToGenericError();
523254721Semaste            error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
524254721Semaste        }
525254721Semaste    }
526254721Semaste    else
527254721Semaste    {
528254721Semaste        error.SetErrorToGenericError();
529254721Semaste        error.SetErrorString ("Couldn't write scalar: its size was zero");
530254721Semaste    }
531254721Semaste    return;
532254721Semaste}
533254721Semaste
534254721Semastevoid
535254721SemasteIRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
536254721Semaste{
537254721Semaste    error.Clear();
538254721Semaste
539254721Semaste    Scalar scalar(address);
540254721Semaste
541254721Semaste    WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
542254721Semaste}
543254721Semaste
544254721Semastevoid
545254721SemasteIRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
546254721Semaste{
547254721Semaste    error.Clear();
548254721Semaste
549254721Semaste    AllocationMap::iterator iter = FindAllocation(process_address, size);
550254721Semaste
551254721Semaste    if (iter == m_allocations.end())
552254721Semaste    {
553254721Semaste        lldb::ProcessSP process_sp = m_process_wp.lock();
554254721Semaste
555254721Semaste        if (process_sp)
556254721Semaste        {
557254721Semaste            process_sp->ReadMemory(process_address, bytes, size, error);
558254721Semaste            return;
559254721Semaste        }
560254721Semaste
561254721Semaste        lldb::TargetSP target_sp = m_target_wp.lock();
562254721Semaste
563254721Semaste        if (target_sp)
564254721Semaste        {
565254721Semaste            Address absolute_address(process_address);
566254721Semaste            target_sp->ReadMemory(absolute_address, false, bytes, size, error);
567254721Semaste            return;
568254721Semaste        }
569254721Semaste
570254721Semaste        error.SetErrorToGenericError();
571254721Semaste        error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
572254721Semaste        return;
573254721Semaste    }
574254721Semaste
575254721Semaste    Allocation &allocation = iter->second;
576254721Semaste
577254721Semaste    uint64_t offset = process_address - allocation.m_process_start;
578254721Semaste
579254721Semaste    lldb::ProcessSP process_sp;
580254721Semaste
581254721Semaste    switch (allocation.m_policy)
582254721Semaste    {
583254721Semaste    default:
584254721Semaste        error.SetErrorToGenericError();
585254721Semaste        error.SetErrorString("Couldn't read: invalid allocation policy");
586254721Semaste        return;
587254721Semaste    case eAllocationPolicyHostOnly:
588254721Semaste        if (!allocation.m_data.GetByteSize())
589254721Semaste        {
590254721Semaste            error.SetErrorToGenericError();
591254721Semaste            error.SetErrorString("Couldn't read: data buffer is empty");
592254721Semaste            return;
593254721Semaste        }
594254721Semaste        ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
595254721Semaste        break;
596254721Semaste    case eAllocationPolicyMirror:
597254721Semaste        process_sp = m_process_wp.lock();
598254721Semaste        if (process_sp)
599254721Semaste        {
600254721Semaste            process_sp->ReadMemory(process_address, bytes, size, error);
601254721Semaste            if (!error.Success())
602254721Semaste                return;
603254721Semaste        }
604254721Semaste        else
605254721Semaste        {
606254721Semaste            if (!allocation.m_data.GetByteSize())
607254721Semaste            {
608254721Semaste                error.SetErrorToGenericError();
609254721Semaste                error.SetErrorString("Couldn't read: data buffer is empty");
610254721Semaste                return;
611254721Semaste            }
612254721Semaste            ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
613254721Semaste        }
614254721Semaste        break;
615254721Semaste    case eAllocationPolicyProcessOnly:
616254721Semaste        process_sp = m_process_wp.lock();
617254721Semaste        if (process_sp)
618254721Semaste        {
619254721Semaste            process_sp->ReadMemory(process_address, bytes, size, error);
620254721Semaste            if (!error.Success())
621254721Semaste                return;
622254721Semaste        }
623254721Semaste        break;
624254721Semaste    }
625254721Semaste
626254721Semaste    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
627254721Semaste    {
628254721Semaste        log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
629254721Semaste                    (uint64_t)process_address,
630254721Semaste                    (uint64_t)bytes,
631254721Semaste                    (uint64_t)size,
632254721Semaste                    (uint64_t)allocation.m_process_start,
633254721Semaste                    (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
634254721Semaste    }
635254721Semaste}
636254721Semaste
637254721Semastevoid
638254721SemasteIRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
639254721Semaste{
640254721Semaste    error.Clear();
641254721Semaste
642254721Semaste    if (size > 0)
643254721Semaste    {
644254721Semaste        DataBufferHeap buf(size, 0);
645254721Semaste        ReadMemory(buf.GetBytes(), process_address, size, error);
646254721Semaste
647254721Semaste        if (!error.Success())
648254721Semaste            return;
649254721Semaste
650254721Semaste        DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
651254721Semaste
652254721Semaste        lldb::offset_t offset = 0;
653254721Semaste
654254721Semaste        switch (size)
655254721Semaste        {
656254721Semaste        default:
657254721Semaste            error.SetErrorToGenericError();
658254721Semaste            error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
659254721Semaste            return;
660254721Semaste        case 1: scalar = extractor.GetU8(&offset);  break;
661254721Semaste        case 2: scalar = extractor.GetU16(&offset); break;
662254721Semaste        case 4: scalar = extractor.GetU32(&offset); break;
663254721Semaste        case 8: scalar = extractor.GetU64(&offset); break;
664254721Semaste        }
665254721Semaste    }
666254721Semaste    else
667254721Semaste    {
668254721Semaste        error.SetErrorToGenericError();
669254721Semaste        error.SetErrorString ("Couldn't read scalar: its size was zero");
670254721Semaste    }
671254721Semaste    return;
672254721Semaste}
673254721Semaste
674254721Semastevoid
675254721SemasteIRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
676254721Semaste{
677254721Semaste    error.Clear();
678254721Semaste
679254721Semaste    Scalar pointer_scalar;
680254721Semaste    ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
681254721Semaste
682254721Semaste    if (!error.Success())
683254721Semaste        return;
684254721Semaste
685254721Semaste    *address = pointer_scalar.ULongLong();
686254721Semaste
687254721Semaste    return;
688254721Semaste}
689254721Semaste
690254721Semastevoid
691254721SemasteIRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
692254721Semaste{
693254721Semaste    error.Clear();
694254721Semaste
695254721Semaste    if (size > 0)
696254721Semaste    {
697254721Semaste        AllocationMap::iterator iter = FindAllocation(process_address, size);
698254721Semaste
699254721Semaste        if (iter == m_allocations.end())
700254721Semaste        {
701254721Semaste            error.SetErrorToGenericError();
702254721Semaste            error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
703254721Semaste            return;
704254721Semaste        }
705254721Semaste
706254721Semaste        Allocation &allocation = iter->second;
707254721Semaste
708254721Semaste        switch (allocation.m_policy)
709254721Semaste        {
710254721Semaste        default:
711254721Semaste            error.SetErrorToGenericError();
712254721Semaste            error.SetErrorString("Couldn't get memory data: invalid allocation policy");
713254721Semaste            return;
714254721Semaste        case eAllocationPolicyProcessOnly:
715254721Semaste            error.SetErrorToGenericError();
716254721Semaste            error.SetErrorString("Couldn't get memory data: memory is only in the target");
717254721Semaste            return;
718254721Semaste        case eAllocationPolicyMirror:
719254721Semaste            {
720254721Semaste                lldb::ProcessSP process_sp = m_process_wp.lock();
721254721Semaste
722254721Semaste                if (!allocation.m_data.GetByteSize())
723254721Semaste                {
724254721Semaste                    error.SetErrorToGenericError();
725254721Semaste                    error.SetErrorString("Couldn't get memory data: data buffer is empty");
726254721Semaste                    return;
727254721Semaste                }
728254721Semaste                if (process_sp)
729254721Semaste                {
730254721Semaste                    process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
731254721Semaste                    if (!error.Success())
732254721Semaste                        return;
733254721Semaste                    uint64_t offset = process_address - allocation.m_process_start;
734254721Semaste                    extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
735254721Semaste                    return;
736254721Semaste                }
737254721Semaste            }
738254721Semaste        case eAllocationPolicyHostOnly:
739254721Semaste            if (!allocation.m_data.GetByteSize())
740254721Semaste            {
741254721Semaste                error.SetErrorToGenericError();
742254721Semaste                error.SetErrorString("Couldn't get memory data: data buffer is empty");
743254721Semaste                return;
744254721Semaste            }
745254721Semaste            uint64_t offset = process_address - allocation.m_process_start;
746254721Semaste            extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
747254721Semaste            return;
748254721Semaste        }
749254721Semaste    }
750254721Semaste    else
751254721Semaste    {
752254721Semaste        error.SetErrorToGenericError();
753254721Semaste        error.SetErrorString ("Couldn't get memory data: its size was zero");
754254721Semaste        return;
755254721Semaste    }
756254721Semaste}
757254721Semaste
758254721Semaste
759