1//===-- IRMemoryMap.cpp -----------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Core/DataBufferHeap.h"
11#include "lldb/Core/DataExtractor.h"
12#include "lldb/Core/Error.h"
13#include "lldb/Core/Log.h"
14#include "lldb/Core/Scalar.h"
15#include "lldb/Expression/IRMemoryMap.h"
16#include "lldb/Target/Process.h"
17#include "lldb/Target/Target.h"
18
19using namespace lldb_private;
20
21IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
22    m_target_wp(target_sp)
23{
24    if (target_sp)
25        m_process_wp = target_sp->GetProcessSP();
26}
27
28IRMemoryMap::~IRMemoryMap ()
29{
30    lldb::ProcessSP process_sp = m_process_wp.lock();
31
32    if (process_sp)
33    {
34        AllocationMap::iterator iter;
35
36        Error err;
37
38        while ((iter = m_allocations.begin()) != m_allocations.end())
39        {
40            err.Clear();
41            if (iter->second.m_leak)
42                m_allocations.erase(iter);
43            else
44                Free(iter->first, err);
45        }
46    }
47}
48
49lldb::addr_t
50IRMemoryMap::FindSpace (size_t size)
51{
52    lldb::TargetSP target_sp = m_target_wp.lock();
53    lldb::ProcessSP process_sp = m_process_wp.lock();
54
55    lldb::addr_t ret = LLDB_INVALID_ADDRESS;
56
57    if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
58    {
59        Error alloc_error;
60
61        ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
62
63        if (!alloc_error.Success())
64            return LLDB_INVALID_ADDRESS;
65        else
66            return ret;
67    }
68
69    for (int iterations = 0; iterations < 16; ++iterations)
70    {
71        lldb::addr_t candidate = LLDB_INVALID_ADDRESS;
72
73        switch (target_sp->GetArchitecture().GetAddressByteSize())
74        {
75        case 4:
76            {
77                uint32_t random_data = rand();
78                candidate = random_data;
79                candidate &= ~0xfffull;
80                break;
81            }
82        case 8:
83            {
84                uint32_t random_low = rand();
85                uint32_t random_high = rand();
86                candidate = random_high;
87                candidate <<= 32ull;
88                candidate |= random_low;
89                candidate &= ~0xfffull;
90                break;
91            }
92        }
93
94        if (IntersectsAllocation(candidate, size))
95            continue;
96
97        ret = candidate;
98
99        return ret;
100    }
101
102    return ret;
103}
104
105IRMemoryMap::AllocationMap::iterator
106IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
107{
108    if (addr == LLDB_INVALID_ADDRESS)
109        return m_allocations.end();
110
111    AllocationMap::iterator iter = m_allocations.lower_bound (addr);
112
113    if (iter == m_allocations.end() ||
114        iter->first > addr)
115    {
116        if (iter == m_allocations.begin())
117            return m_allocations.end();
118        iter--;
119    }
120
121    if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
122        return iter;
123
124    return m_allocations.end();
125}
126
127bool
128IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size)
129{
130    if (addr == LLDB_INVALID_ADDRESS)
131        return false;
132
133    AllocationMap::iterator iter = m_allocations.lower_bound (addr);
134
135    if (iter == m_allocations.end() ||
136        iter->first > addr)
137    {
138        if (iter == m_allocations.begin())
139            return false;
140
141        iter--;
142    }
143
144    while (iter != m_allocations.end() && iter->second.m_process_alloc < addr + size)
145    {
146        if (iter->second.m_process_start + iter->second.m_size > addr)
147            return true;
148
149        ++iter;
150    }
151
152    return false;
153}
154
155lldb::ByteOrder
156IRMemoryMap::GetByteOrder()
157{
158    lldb::ProcessSP process_sp = m_process_wp.lock();
159
160    if (process_sp)
161        return process_sp->GetByteOrder();
162
163    lldb::TargetSP target_sp = m_target_wp.lock();
164
165    if (target_sp)
166        return target_sp->GetArchitecture().GetByteOrder();
167
168    return lldb::eByteOrderInvalid;
169}
170
171uint32_t
172IRMemoryMap::GetAddressByteSize()
173{
174    lldb::ProcessSP process_sp = m_process_wp.lock();
175
176    if (process_sp)
177        return process_sp->GetAddressByteSize();
178
179    lldb::TargetSP target_sp = m_target_wp.lock();
180
181    if (target_sp)
182        return target_sp->GetArchitecture().GetAddressByteSize();
183
184    return UINT32_MAX;
185}
186
187ExecutionContextScope *
188IRMemoryMap::GetBestExecutionContextScope()
189{
190    lldb::ProcessSP process_sp = m_process_wp.lock();
191
192    if (process_sp)
193        return process_sp.get();
194
195    lldb::TargetSP target_sp = m_target_wp.lock();
196
197    if (target_sp)
198        return target_sp.get();
199
200    return NULL;
201}
202
203IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
204                                     lldb::addr_t process_start,
205                                     size_t size,
206                                     uint32_t permissions,
207                                     uint8_t alignment,
208                                     AllocationPolicy policy) :
209    m_process_alloc (process_alloc),
210    m_process_start (process_start),
211    m_size (size),
212    m_permissions (permissions),
213    m_alignment (alignment),
214    m_policy (policy),
215    m_leak (false)
216{
217    switch (policy)
218    {
219        default:
220            assert (0 && "We cannot reach this!");
221        case eAllocationPolicyHostOnly:
222            m_data.SetByteSize(size);
223            memset(m_data.GetBytes(), 0, size);
224            break;
225        case eAllocationPolicyProcessOnly:
226            break;
227        case eAllocationPolicyMirror:
228            m_data.SetByteSize(size);
229            memset(m_data.GetBytes(), 0, size);
230            break;
231    }
232}
233
234lldb::addr_t
235IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
236{
237    error.Clear();
238
239    lldb::ProcessSP process_sp;
240    lldb::addr_t    allocation_address  = LLDB_INVALID_ADDRESS;
241    lldb::addr_t    aligned_address     = LLDB_INVALID_ADDRESS;
242
243    size_t          alignment_mask = alignment - 1;
244    size_t          allocation_size;
245
246    if (size == 0)
247        allocation_size = alignment;
248    else
249        allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
250
251    switch (policy)
252    {
253    default:
254        error.SetErrorToGenericError();
255        error.SetErrorString("Couldn't malloc: invalid allocation policy");
256        return LLDB_INVALID_ADDRESS;
257    case eAllocationPolicyHostOnly:
258        allocation_address = FindSpace(allocation_size);
259        if (allocation_address == LLDB_INVALID_ADDRESS)
260        {
261            error.SetErrorToGenericError();
262            error.SetErrorString("Couldn't malloc: address space is full");
263            return LLDB_INVALID_ADDRESS;
264        }
265        break;
266    case eAllocationPolicyMirror:
267        process_sp = m_process_wp.lock();
268        if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
269        {
270            allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
271            if (!error.Success())
272                return LLDB_INVALID_ADDRESS;
273        }
274        else
275        {
276            policy = eAllocationPolicyHostOnly;
277            allocation_address = FindSpace(allocation_size);
278            if (allocation_address == LLDB_INVALID_ADDRESS)
279            {
280                error.SetErrorToGenericError();
281                error.SetErrorString("Couldn't malloc: address space is full");
282                return LLDB_INVALID_ADDRESS;
283            }
284        }
285        break;
286    case eAllocationPolicyProcessOnly:
287        process_sp = m_process_wp.lock();
288        if (process_sp)
289        {
290            if (process_sp->CanJIT() && process_sp->IsAlive())
291            {
292                allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
293                if (!error.Success())
294                    return LLDB_INVALID_ADDRESS;
295            }
296            else
297            {
298                error.SetErrorToGenericError();
299                error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
300                return LLDB_INVALID_ADDRESS;
301            }
302        }
303        else
304        {
305            error.SetErrorToGenericError();
306            error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
307            return LLDB_INVALID_ADDRESS;
308        }
309        break;
310    }
311
312
313    lldb::addr_t mask = alignment - 1;
314    aligned_address = (allocation_address + mask) & (~mask);
315
316    m_allocations[aligned_address] = Allocation(allocation_address,
317                                                aligned_address,
318                                                allocation_size,
319                                                permissions,
320                                                alignment,
321                                                policy);
322
323    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
324    {
325        const char * policy_string;
326
327        switch (policy)
328        {
329        default:
330            policy_string = "<invalid policy>";
331            break;
332        case eAllocationPolicyHostOnly:
333            policy_string = "eAllocationPolicyHostOnly";
334            break;
335        case eAllocationPolicyProcessOnly:
336            policy_string = "eAllocationPolicyProcessOnly";
337            break;
338        case eAllocationPolicyMirror:
339            policy_string = "eAllocationPolicyMirror";
340            break;
341        }
342
343        log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
344                    (uint64_t)allocation_size,
345                    (uint64_t)alignment,
346                    (uint64_t)permissions,
347                    policy_string,
348                    aligned_address);
349    }
350
351    return aligned_address;
352}
353
354void
355IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
356{
357    error.Clear();
358
359    AllocationMap::iterator iter = m_allocations.find(process_address);
360
361    if (iter == m_allocations.end())
362    {
363        error.SetErrorToGenericError();
364        error.SetErrorString("Couldn't leak: allocation doesn't exist");
365        return;
366    }
367
368    Allocation &allocation = iter->second;
369
370    allocation.m_leak = true;
371}
372
373void
374IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
375{
376    error.Clear();
377
378    AllocationMap::iterator iter = m_allocations.find(process_address);
379
380    if (iter == m_allocations.end())
381    {
382        error.SetErrorToGenericError();
383        error.SetErrorString("Couldn't free: allocation doesn't exist");
384        return;
385    }
386
387    Allocation &allocation = iter->second;
388
389    switch (allocation.m_policy)
390    {
391    default:
392    case eAllocationPolicyHostOnly:
393        {
394            lldb::ProcessSP process_sp = m_process_wp.lock();
395            if (process_sp)
396            {
397                if (process_sp->CanJIT() && process_sp->IsAlive())
398                    process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
399            }
400
401            break;
402        }
403    case eAllocationPolicyMirror:
404    case eAllocationPolicyProcessOnly:
405        {
406            lldb::ProcessSP process_sp = m_process_wp.lock();
407            if (process_sp)
408                process_sp->DeallocateMemory(allocation.m_process_alloc);
409        }
410    }
411
412    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
413    {
414        log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
415                    (uint64_t)process_address,
416                    iter->second.m_process_start,
417                    iter->second.m_process_start + iter->second.m_size);
418    }
419
420    m_allocations.erase(iter);
421}
422
423void
424IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
425{
426    error.Clear();
427
428    AllocationMap::iterator iter = FindAllocation(process_address, size);
429
430    if (iter == m_allocations.end())
431    {
432        lldb::ProcessSP process_sp = m_process_wp.lock();
433
434        if (process_sp)
435        {
436            process_sp->WriteMemory(process_address, bytes, size, error);
437            return;
438        }
439
440        error.SetErrorToGenericError();
441        error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
442        return;
443    }
444
445    Allocation &allocation = iter->second;
446
447    uint64_t offset = process_address - allocation.m_process_start;
448
449    lldb::ProcessSP process_sp;
450
451    switch (allocation.m_policy)
452    {
453    default:
454        error.SetErrorToGenericError();
455        error.SetErrorString("Couldn't write: invalid allocation policy");
456        return;
457    case eAllocationPolicyHostOnly:
458        if (!allocation.m_data.GetByteSize())
459        {
460            error.SetErrorToGenericError();
461            error.SetErrorString("Couldn't write: data buffer is empty");
462            return;
463        }
464        ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
465        break;
466    case eAllocationPolicyMirror:
467        if (!allocation.m_data.GetByteSize())
468        {
469            error.SetErrorToGenericError();
470            error.SetErrorString("Couldn't write: data buffer is empty");
471            return;
472        }
473        ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
474        process_sp = m_process_wp.lock();
475        if (process_sp)
476        {
477            process_sp->WriteMemory(process_address, bytes, size, error);
478            if (!error.Success())
479                return;
480        }
481        break;
482    case eAllocationPolicyProcessOnly:
483        process_sp = m_process_wp.lock();
484        if (process_sp)
485        {
486            process_sp->WriteMemory(process_address, bytes, size, error);
487            if (!error.Success())
488                return;
489        }
490        break;
491    }
492
493    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
494    {
495        log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
496                    (uint64_t)process_address,
497                    (uint64_t)bytes,
498                    (uint64_t)size,
499                    (uint64_t)allocation.m_process_start,
500                    (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
501    }
502}
503
504void
505IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
506{
507    error.Clear();
508
509    if (size == UINT32_MAX)
510        size = scalar.GetByteSize();
511
512    if (size > 0)
513    {
514        uint8_t buf[32];
515        const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
516        if (mem_size > 0)
517        {
518            return WriteMemory(process_address, buf, mem_size, error);
519        }
520        else
521        {
522            error.SetErrorToGenericError();
523            error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
524        }
525    }
526    else
527    {
528        error.SetErrorToGenericError();
529        error.SetErrorString ("Couldn't write scalar: its size was zero");
530    }
531    return;
532}
533
534void
535IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
536{
537    error.Clear();
538
539    Scalar scalar(address);
540
541    WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
542}
543
544void
545IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
546{
547    error.Clear();
548
549    AllocationMap::iterator iter = FindAllocation(process_address, size);
550
551    if (iter == m_allocations.end())
552    {
553        lldb::ProcessSP process_sp = m_process_wp.lock();
554
555        if (process_sp)
556        {
557            process_sp->ReadMemory(process_address, bytes, size, error);
558            return;
559        }
560
561        lldb::TargetSP target_sp = m_target_wp.lock();
562
563        if (target_sp)
564        {
565            Address absolute_address(process_address);
566            target_sp->ReadMemory(absolute_address, false, bytes, size, error);
567            return;
568        }
569
570        error.SetErrorToGenericError();
571        error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
572        return;
573    }
574
575    Allocation &allocation = iter->second;
576
577    uint64_t offset = process_address - allocation.m_process_start;
578
579    lldb::ProcessSP process_sp;
580
581    switch (allocation.m_policy)
582    {
583    default:
584        error.SetErrorToGenericError();
585        error.SetErrorString("Couldn't read: invalid allocation policy");
586        return;
587    case eAllocationPolicyHostOnly:
588        if (!allocation.m_data.GetByteSize())
589        {
590            error.SetErrorToGenericError();
591            error.SetErrorString("Couldn't read: data buffer is empty");
592            return;
593        }
594        ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
595        break;
596    case eAllocationPolicyMirror:
597        process_sp = m_process_wp.lock();
598        if (process_sp)
599        {
600            process_sp->ReadMemory(process_address, bytes, size, error);
601            if (!error.Success())
602                return;
603        }
604        else
605        {
606            if (!allocation.m_data.GetByteSize())
607            {
608                error.SetErrorToGenericError();
609                error.SetErrorString("Couldn't read: data buffer is empty");
610                return;
611            }
612            ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
613        }
614        break;
615    case eAllocationPolicyProcessOnly:
616        process_sp = m_process_wp.lock();
617        if (process_sp)
618        {
619            process_sp->ReadMemory(process_address, bytes, size, error);
620            if (!error.Success())
621                return;
622        }
623        break;
624    }
625
626    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
627    {
628        log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
629                    (uint64_t)process_address,
630                    (uint64_t)bytes,
631                    (uint64_t)size,
632                    (uint64_t)allocation.m_process_start,
633                    (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
634    }
635}
636
637void
638IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
639{
640    error.Clear();
641
642    if (size > 0)
643    {
644        DataBufferHeap buf(size, 0);
645        ReadMemory(buf.GetBytes(), process_address, size, error);
646
647        if (!error.Success())
648            return;
649
650        DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
651
652        lldb::offset_t offset = 0;
653
654        switch (size)
655        {
656        default:
657            error.SetErrorToGenericError();
658            error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
659            return;
660        case 1: scalar = extractor.GetU8(&offset);  break;
661        case 2: scalar = extractor.GetU16(&offset); break;
662        case 4: scalar = extractor.GetU32(&offset); break;
663        case 8: scalar = extractor.GetU64(&offset); break;
664        }
665    }
666    else
667    {
668        error.SetErrorToGenericError();
669        error.SetErrorString ("Couldn't read scalar: its size was zero");
670    }
671    return;
672}
673
674void
675IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
676{
677    error.Clear();
678
679    Scalar pointer_scalar;
680    ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
681
682    if (!error.Success())
683        return;
684
685    *address = pointer_scalar.ULongLong();
686
687    return;
688}
689
690void
691IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
692{
693    error.Clear();
694
695    if (size > 0)
696    {
697        AllocationMap::iterator iter = FindAllocation(process_address, size);
698
699        if (iter == m_allocations.end())
700        {
701            error.SetErrorToGenericError();
702            error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
703            return;
704        }
705
706        Allocation &allocation = iter->second;
707
708        switch (allocation.m_policy)
709        {
710        default:
711            error.SetErrorToGenericError();
712            error.SetErrorString("Couldn't get memory data: invalid allocation policy");
713            return;
714        case eAllocationPolicyProcessOnly:
715            error.SetErrorToGenericError();
716            error.SetErrorString("Couldn't get memory data: memory is only in the target");
717            return;
718        case eAllocationPolicyMirror:
719            {
720                lldb::ProcessSP process_sp = m_process_wp.lock();
721
722                if (!allocation.m_data.GetByteSize())
723                {
724                    error.SetErrorToGenericError();
725                    error.SetErrorString("Couldn't get memory data: data buffer is empty");
726                    return;
727                }
728                if (process_sp)
729                {
730                    process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
731                    if (!error.Success())
732                        return;
733                    uint64_t offset = process_address - allocation.m_process_start;
734                    extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
735                    return;
736                }
737            }
738        case eAllocationPolicyHostOnly:
739            if (!allocation.m_data.GetByteSize())
740            {
741                error.SetErrorToGenericError();
742                error.SetErrorString("Couldn't get memory data: data buffer is empty");
743                return;
744            }
745            uint64_t offset = process_address - allocation.m_process_start;
746            extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
747            return;
748        }
749    }
750    else
751    {
752        error.SetErrorToGenericError();
753        error.SetErrorString ("Couldn't get memory data: its size was zero");
754        return;
755    }
756}
757
758
759