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