blob: 9a0f034dc625fb5e498aa8e37dda4429abdc0d6e [file] [log] [blame]
Sean Callanan5a1af4e2013-04-05 02:22:57 +00001//===-- 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
Sean Callanan35005f72013-04-12 18:10:34 +000010#include "lldb/Core/DataBufferHeap.h"
11#include "lldb/Core/DataExtractor.h"
Sean Callanan5a1af4e2013-04-05 02:22:57 +000012#include "lldb/Core/Error.h"
13#include "lldb/Core/Log.h"
Sean Callanan35005f72013-04-12 18:10:34 +000014#include "lldb/Core/Scalar.h"
Sean Callanan5a1af4e2013-04-05 02:22:57 +000015#include "lldb/Expression/IRMemoryMap.h"
16#include "lldb/Target/Process.h"
Sean Callanan35005f72013-04-12 18:10:34 +000017#include "lldb/Target/Target.h"
Sean Callanan5a1af4e2013-04-05 02:22:57 +000018
19using namespace lldb_private;
20
Sean Callanan35005f72013-04-12 18:10:34 +000021IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
Sean Callanan35005f72013-04-12 18:10:34 +000022 m_target_wp(target_sp)
Sean Callanan5a1af4e2013-04-05 02:22:57 +000023{
Sean Callananb024d872013-04-15 17:12:47 +000024 if (target_sp)
25 m_process_wp = target_sp->GetProcessSP();
Sean Callanan5a1af4e2013-04-05 02:22:57 +000026}
27
28IRMemoryMap::~IRMemoryMap ()
29{
30 lldb::ProcessSP process_sp = m_process_wp.lock();
31
32 if (process_sp)
33 {
Sean Callananbb777042013-05-16 17:30:37 +000034 AllocationMap::iterator iter;
35
36 Error err;
37
38 while ((iter = m_allocations.begin()) != m_allocations.end())
Sean Callanan5a1af4e2013-04-05 02:22:57 +000039 {
Sean Callananbb777042013-05-16 17:30:37 +000040 err.Clear();
Sean Callananfbf5c682013-05-22 22:49:06 +000041 if (iter->second.m_leak)
42 m_allocations.erase(iter);
43 else
44 Free(iter->first, err);
Sean Callanan5a1af4e2013-04-05 02:22:57 +000045 }
46 }
47}
48
49lldb::addr_t
50IRMemoryMap::FindSpace (size_t size)
51{
Sean Callananbb9945f2013-04-19 01:51:24 +000052 lldb::TargetSP target_sp = m_target_wp.lock();
53 lldb::ProcessSP process_sp = m_process_wp.lock();
Sean Callanan5a1af4e2013-04-05 02:22:57 +000054
Sean Callananbb9945f2013-04-19 01:51:24 +000055 lldb::addr_t ret = LLDB_INVALID_ADDRESS;
Sean Callanan5a1af4e2013-04-05 02:22:57 +000056
Sean Callanandf565402013-04-27 02:19:33 +000057 if (process_sp && process_sp->CanJIT())
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
Sean Callananbb777042013-05-16 17:30:37 +000069 if (process_sp)
70 {
71 ret = process_sp->GetReservationCache().Find(size);
72
73 if (ret != LLDB_INVALID_ADDRESS)
74 return ret;
75 }
76
Sean Callananbb9945f2013-04-19 01:51:24 +000077 for (int iterations = 0; iterations < 16; ++iterations)
Sean Callanan5a1af4e2013-04-05 02:22:57 +000078 {
Jim Ingham5c42d8a2013-05-15 18:27:08 +000079 lldb::addr_t candidate = LLDB_INVALID_ADDRESS;
Sean Callananbb9945f2013-04-19 01:51:24 +000080
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;
Sean Callananbb777042013-05-16 17:30:37 +0000115
116 if (process_sp)
117 process_sp->GetReservationCache().Reserve(candidate, size);
118
119 return ret;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000120 }
121
Sean Callananbb9945f2013-04-19 01:51:24 +0000122 return ret;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000123}
124
125IRMemoryMap::AllocationMap::iterator
126IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
127{
Sean Callanan1582ee62013-04-18 22:06:33 +0000128 if (addr == LLDB_INVALID_ADDRESS)
129 return m_allocations.end();
130
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000131 AllocationMap::iterator iter = m_allocations.lower_bound (addr);
132
Sean Callanan14b1bae2013-04-16 23:25:35 +0000133 if (iter == m_allocations.end() ||
134 iter->first > addr)
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000135 {
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
Sean Callananbb9945f2013-04-19 01:51:24 +0000147bool
148IRMemoryMap::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
Sean Callanan35005f72013-04-12 18:10:34 +0000175lldb::ByteOrder
176IRMemoryMap::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)
Sean Callanan08052af2013-04-17 07:50:58 +0000186 return target_sp->GetArchitecture().GetByteOrder();
Sean Callanan35005f72013-04-12 18:10:34 +0000187
188 return lldb::eByteOrderInvalid;
189}
190
191uint32_t
192IRMemoryMap::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)
Sean Callanan08052af2013-04-17 07:50:58 +0000202 return target_sp->GetArchitecture().GetAddressByteSize();
Sean Callanan35005f72013-04-12 18:10:34 +0000203
204 return UINT32_MAX;
205}
206
207ExecutionContextScope *
208IRMemoryMap::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
Sean Callanand2562502013-04-19 17:44:40 +0000223IRMemoryMap::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
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000254lldb::addr_t
255IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
256{
Sean Callanan08052af2013-04-17 07:50:58 +0000257 error.Clear();
258
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000259 lldb::ProcessSP process_sp;
260 lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
261 lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
Matt Kopec750dcc32013-04-26 17:48:01 +0000262
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;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000270
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:
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000287 process_sp = m_process_wp.lock();
Sean Callananbb9945f2013-04-19 01:51:24 +0000288 if (process_sp && process_sp->CanJIT())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000289 {
290 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
291 if (!error.Success())
292 return LLDB_INVALID_ADDRESS;
293 }
294 else
295 {
Sean Callananbb9945f2013-04-19 01:51:24 +0000296 policy = eAllocationPolicyHostOnly;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000297 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:
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000307 process_sp = m_process_wp.lock();
308 if (process_sp)
309 {
Sean Callananbb9945f2013-04-19 01:51:24 +0000310 if (process_sp->CanJIT())
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");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000320 return LLDB_INVALID_ADDRESS;
Sean Callananbb9945f2013-04-19 01:51:24 +0000321 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000322 }
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
Sean Callanand2562502013-04-19 17:44:40 +0000336 m_allocations[aligned_address] = Allocation(allocation_address,
337 aligned_address,
Matt Kopec750dcc32013-04-26 17:48:01 +0000338 allocation_size,
Sean Callanand2562502013-04-19 17:44:40 +0000339 permissions,
340 alignment,
341 policy);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000342
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 (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx",
Matt Kopec750dcc32013-04-26 17:48:01 +0000364 (uint64_t)allocation_size,
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000365 (uint64_t)alignment,
366 (uint64_t)permissions,
367 policy_string,
368 aligned_address);
369 }
370
371 return aligned_address;
372}
373
374void
Sean Callananfbf5c682013-05-22 22:49:06 +0000375IRMemoryMap::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
393void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000394IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
395{
Sean Callanan08052af2013-04-17 07:50:58 +0000396 error.Clear();
397
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000398 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:
Sean Callanandf565402013-04-27 02:19:33 +0000413 {
414 lldb::ProcessSP process_sp = m_process_wp.lock();
Sean Callananbb777042013-05-16 17:30:37 +0000415 if (process_sp)
416 {
417 if (process_sp->CanJIT())
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
Sean Callanandf565402013-04-27 02:19:33 +0000423 break;
424 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000425 case eAllocationPolicyMirror:
426 case eAllocationPolicyProcessOnly:
Sean Callanandf565402013-04-27 02:19:33 +0000427 {
428 lldb::ProcessSP process_sp = m_process_wp.lock();
429 if (process_sp)
430 process_sp->DeallocateMemory(allocation.m_process_alloc);
431 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000432 }
433
434 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
435 {
436 log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
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
445void
446IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
447{
Sean Callanan08052af2013-04-17 07:50:58 +0000448 error.Clear();
449
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000450 AllocationMap::iterator iter = FindAllocation(process_address, size);
451
452 if (iter == m_allocations.end())
453 {
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000454 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
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000462 error.SetErrorToGenericError();
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000463 error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000464 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:
Sean Callanand2562502013-04-19 17:44:40 +0000480 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000481 {
482 error.SetErrorToGenericError();
483 error.SetErrorString("Couldn't write: data buffer is empty");
484 return;
485 }
Sean Callanand2562502013-04-19 17:44:40 +0000486 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000487 break;
488 case eAllocationPolicyMirror:
Sean Callanand2562502013-04-19 17:44:40 +0000489 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000490 {
491 error.SetErrorToGenericError();
492 error.SetErrorString("Couldn't write: data buffer is empty");
493 return;
494 }
Sean Callanand2562502013-04-19 17:44:40 +0000495 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000496 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%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
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
526void
Sean Callanan35005f72013-04-12 18:10:34 +0000527IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
Sean Callanan08052af2013-04-17 07:50:58 +0000528{
529 error.Clear();
530
Sean Callanan35005f72013-04-12 18:10:34 +0000531 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
556void
Sean Callananf8043fa2013-04-12 21:40:34 +0000557IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
558{
Sean Callanan08052af2013-04-17 07:50:58 +0000559 error.Clear();
560
Sean Callananf8043fa2013-04-12 21:40:34 +0000561 Scalar scalar(address);
562
563 WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
564}
565
Sean Callananf8043fa2013-04-12 21:40:34 +0000566void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000567IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
568{
Sean Callanan08052af2013-04-17 07:50:58 +0000569 error.Clear();
570
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000571 AllocationMap::iterator iter = FindAllocation(process_address, size);
572
573 if (iter == m_allocations.end())
574 {
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000575 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
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000592 error.SetErrorToGenericError();
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000593 error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000594 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:
Sean Callanand2562502013-04-19 17:44:40 +0000610 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000611 {
612 error.SetErrorToGenericError();
613 error.SetErrorString("Couldn't read: data buffer is empty");
614 return;
615 }
Sean Callanand2562502013-04-19 17:44:40 +0000616 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000617 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 {
Sean Callanand2562502013-04-19 17:44:40 +0000628 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000629 {
630 error.SetErrorToGenericError();
631 error.SetErrorString("Couldn't read: data buffer is empty");
632 return;
633 }
Sean Callanand2562502013-04-19 17:44:40 +0000634 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000635 }
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%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
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}
Sean Callanan35005f72013-04-12 18:10:34 +0000658
659void
660IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
Sean Callanan08052af2013-04-17 07:50:58 +0000661{
662 error.Clear();
663
Sean Callanan35005f72013-04-12 18:10:34 +0000664 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 %lld", (unsigned long long)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();
Sean Callanan458ae1c2013-04-13 02:06:42 +0000691 error.SetErrorString ("Couldn't read scalar: its size was zero");
Sean Callanan35005f72013-04-12 18:10:34 +0000692 }
693 return;
694}
695
Sean Callanan458ae1c2013-04-13 02:06:42 +0000696void
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000697IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
698{
Sean Callanan08052af2013-04-17 07:50:58 +0000699 error.Clear();
700
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000701 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
712void
Sean Callanan458ae1c2013-04-13 02:06:42 +0000713IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
714{
Sean Callanan08052af2013-04-17 07:50:58 +0000715 error.Clear();
716
Sean Callanan458ae1c2013-04-13 02:06:42 +0000717 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%llx..0x%llx)", (unsigned long long)process_address, (unsigned long long)(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;
Sean Callanan458ae1c2013-04-13 02:06:42 +0000740 case eAllocationPolicyMirror:
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000741 {
742 lldb::ProcessSP process_sp = m_process_wp.lock();
743
Sean Callanand2562502013-04-19 17:44:40 +0000744 if (!allocation.m_data.GetByteSize())
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000745 {
746 error.SetErrorToGenericError();
747 error.SetErrorString("Couldn't get memory data: data buffer is empty");
748 return;
749 }
750 if (process_sp)
751 {
Sean Callanand2562502013-04-19 17:44:40 +0000752 process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000753 if (!error.Success())
754 return;
755 uint64_t offset = process_address - allocation.m_process_start;
Sean Callanand2562502013-04-19 17:44:40 +0000756 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000757 return;
758 }
759 }
760 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000761 if (!allocation.m_data.GetByteSize())
Sean Callanan458ae1c2013-04-13 02:06:42 +0000762 {
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;
Sean Callanand2562502013-04-19 17:44:40 +0000768 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
Sean Callanan458ae1c2013-04-13 02:06:42 +0000769 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