blob: a58225bfa17237b21702c02f820f33966e251f03 [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
21IRMemoryMap::IRMemoryMap (lldb::ProcessSP process_sp) :
Sean Callanan35005f72013-04-12 18:10:34 +000022 m_process_wp(process_sp),
23 m_target_wp(process_sp->GetTarget().shared_from_this())
24{
25}
26
27IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
28 m_process_wp(),
29 m_target_wp(target_sp)
Sean Callanan5a1af4e2013-04-05 02:22:57 +000030{
31}
32
33IRMemoryMap::~IRMemoryMap ()
34{
35 lldb::ProcessSP process_sp = m_process_wp.lock();
36
37 if (process_sp)
38 {
39 for (AllocationMap::value_type &allocation : m_allocations)
40 {
41 if (allocation.second.m_policy == eAllocationPolicyMirror ||
42 allocation.second.m_policy == eAllocationPolicyHostOnly)
43 process_sp->DeallocateMemory(allocation.second.m_process_alloc);
44
45 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
46 {
47 log->Printf("IRMemoryMap::~IRMemoryMap deallocated [0x%llx..0x%llx)",
48 (uint64_t)allocation.second.m_process_start,
49 (uint64_t)allocation.second.m_process_start + (uint64_t)allocation.second.m_size);
50 }
51 }
52 }
53}
54
55lldb::addr_t
56IRMemoryMap::FindSpace (size_t size)
57{
58 // Yup, this is just plain O(n) insertion. We'll use a range tree if we
59 // start caring.
60
61 lldb::addr_t remote_address = 0x1000; // skip first page of memory
62
63 for (AllocationMap::value_type &allocation : m_allocations)
64 {
65 if (remote_address < allocation.second.m_process_start &&
66 remote_address + size <= allocation.second.m_process_start)
67 return remote_address;
68
69 remote_address = allocation.second.m_process_start = allocation.second.m_size;
70 }
71
72 if (remote_address + size < remote_address)
73 return LLDB_INVALID_ADDRESS; // massively unlikely
74
75 return remote_address;
76}
77
78bool
79IRMemoryMap::ContainsHostOnlyAllocations ()
80{
81 for (AllocationMap::value_type &allocation : m_allocations)
82 {
83 if (allocation.second.m_policy == eAllocationPolicyHostOnly)
84 return true;
85 }
86
87 return false;
88}
89
90IRMemoryMap::AllocationMap::iterator
91IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
92{
93 AllocationMap::iterator iter = m_allocations.lower_bound (addr);
94
95 if (iter == m_allocations.end())
96 return iter;
97
98 if (iter->first > addr)
99 {
100 if (iter == m_allocations.begin())
101 return m_allocations.end();
102 iter--;
103 }
104
105 if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
106 return iter;
107
108 return m_allocations.end();
109}
110
Sean Callanan35005f72013-04-12 18:10:34 +0000111lldb::ByteOrder
112IRMemoryMap::GetByteOrder()
113{
114 lldb::ProcessSP process_sp = m_process_wp.lock();
115
116 if (process_sp)
117 return process_sp->GetByteOrder();
118
119 lldb::TargetSP target_sp = m_target_wp.lock();
120
121 if (target_sp)
122 return target_sp->GetDefaultArchitecture().GetByteOrder();
123
124 return lldb::eByteOrderInvalid;
125}
126
127uint32_t
128IRMemoryMap::GetAddressByteSize()
129{
130 lldb::ProcessSP process_sp = m_process_wp.lock();
131
132 if (process_sp)
133 return process_sp->GetAddressByteSize();
134
135 lldb::TargetSP target_sp = m_target_wp.lock();
136
137 if (target_sp)
138 return target_sp->GetDefaultArchitecture().GetAddressByteSize();
139
140 return UINT32_MAX;
141}
142
143ExecutionContextScope *
144IRMemoryMap::GetBestExecutionContextScope()
145{
146 lldb::ProcessSP process_sp = m_process_wp.lock();
147
148 if (process_sp)
149 return process_sp.get();
150
151 lldb::TargetSP target_sp = m_target_wp.lock();
152
153 if (target_sp)
154 return target_sp.get();
155
156 return NULL;
157}
158
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000159lldb::addr_t
160IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
161{
162 lldb::ProcessSP process_sp;
163 lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
164 lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
165
166 size_t allocation_size = (size ? size : 1) + alignment - 1;
167
168 switch (policy)
169 {
170 default:
171 error.SetErrorToGenericError();
172 error.SetErrorString("Couldn't malloc: invalid allocation policy");
173 return LLDB_INVALID_ADDRESS;
174 case eAllocationPolicyHostOnly:
175 allocation_address = FindSpace(allocation_size);
176 if (allocation_address == LLDB_INVALID_ADDRESS)
177 {
178 error.SetErrorToGenericError();
179 error.SetErrorString("Couldn't malloc: address space is full");
180 return LLDB_INVALID_ADDRESS;
181 }
182 break;
183 case eAllocationPolicyMirror:
184 if (ContainsHostOnlyAllocations())
185 {
186 error.SetErrorToGenericError();
187 error.SetErrorString("Couldn't malloc: host-only allocations are polluting the address space");
188 return LLDB_INVALID_ADDRESS;
189 }
190 process_sp = m_process_wp.lock();
191 if (process_sp)
192 {
193 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
194 if (!error.Success())
195 return LLDB_INVALID_ADDRESS;
196 }
197 else
198 {
199 allocation_address = FindSpace(allocation_size);
200 if (allocation_address == LLDB_INVALID_ADDRESS)
201 {
202 error.SetErrorToGenericError();
203 error.SetErrorString("Couldn't malloc: address space is full");
204 return LLDB_INVALID_ADDRESS;
205 }
206 }
207 break;
208 case eAllocationPolicyProcessOnly:
209 if (ContainsHostOnlyAllocations())
210 {
211 error.SetErrorToGenericError();
212 error.SetErrorString("Couldn't malloc: host-only allocations are polluting the address space");
213 return LLDB_INVALID_ADDRESS;
214 }
215 process_sp = m_process_wp.lock();
216 if (process_sp)
217 {
218 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
219 if (!error.Success())
220 return LLDB_INVALID_ADDRESS;
221 }
222 else
223 {
224 error.SetErrorToGenericError();
225 error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
226 return LLDB_INVALID_ADDRESS;
227 }
228 break;
229 }
230
231
232 lldb::addr_t mask = alignment - 1;
233 aligned_address = (allocation_address + mask) & (~mask);
234
235 Allocation &allocation(m_allocations[aligned_address]);
236
237 allocation.m_process_alloc = allocation_address;
238 allocation.m_process_start = aligned_address;
239 allocation.m_size = size;
240 allocation.m_permissions = permissions;
241 allocation.m_alignment = alignment;
242 allocation.m_policy = policy;
243
244 switch (policy)
245 {
246 default:
247 assert (0 && "We cannot reach this!");
248 case eAllocationPolicyHostOnly:
249 allocation.m_data.reset(new DataBufferHeap(size, 0));
250 break;
251 case eAllocationPolicyProcessOnly:
252 break;
253 case eAllocationPolicyMirror:
254 allocation.m_data.reset(new DataBufferHeap(size, 0));
255 break;
256 }
257
258 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
259 {
260 const char * policy_string;
261
262 switch (policy)
263 {
264 default:
265 policy_string = "<invalid policy>";
266 break;
267 case eAllocationPolicyHostOnly:
268 policy_string = "eAllocationPolicyHostOnly";
269 break;
270 case eAllocationPolicyProcessOnly:
271 policy_string = "eAllocationPolicyProcessOnly";
272 break;
273 case eAllocationPolicyMirror:
274 policy_string = "eAllocationPolicyMirror";
275 break;
276 }
277
278 log->Printf("IRMemoryMap::Malloc (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx",
279 (uint64_t)size,
280 (uint64_t)alignment,
281 (uint64_t)permissions,
282 policy_string,
283 aligned_address);
284 }
285
286 return aligned_address;
287}
288
289void
290IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
291{
292 AllocationMap::iterator iter = m_allocations.find(process_address);
293
294 if (iter == m_allocations.end())
295 {
296 error.SetErrorToGenericError();
297 error.SetErrorString("Couldn't free: allocation doesn't exist");
298 return;
299 }
300
301 Allocation &allocation = iter->second;
302
303 switch (allocation.m_policy)
304 {
305 default:
306 case eAllocationPolicyHostOnly:
307 break;
308 case eAllocationPolicyMirror:
309 case eAllocationPolicyProcessOnly:
310 lldb::ProcessSP process_sp = m_process_wp.lock();
311 if (process_sp)
312 process_sp->DeallocateMemory(allocation.m_process_alloc);
313 }
314
315 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
316 {
317 log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
318 (uint64_t)process_address,
319 iter->second.m_process_start,
320 iter->second.m_process_start + iter->second.m_size);
321 }
322
323 m_allocations.erase(iter);
324}
325
326void
327IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
328{
329 AllocationMap::iterator iter = FindAllocation(process_address, size);
330
331 if (iter == m_allocations.end())
332 {
333 error.SetErrorToGenericError();
334 error.SetErrorString("Couldn't write: no allocation contains the target range");
335 return;
336 }
337
338 Allocation &allocation = iter->second;
339
340 uint64_t offset = process_address - allocation.m_process_start;
341
342 lldb::ProcessSP process_sp;
343
344 switch (allocation.m_policy)
345 {
346 default:
347 error.SetErrorToGenericError();
348 error.SetErrorString("Couldn't write: invalid allocation policy");
349 return;
350 case eAllocationPolicyHostOnly:
351 if (!allocation.m_data)
352 {
353 error.SetErrorToGenericError();
354 error.SetErrorString("Couldn't write: data buffer is empty");
355 return;
356 }
357 ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
358 break;
359 case eAllocationPolicyMirror:
360 if (!allocation.m_data)
361 {
362 error.SetErrorToGenericError();
363 error.SetErrorString("Couldn't write: data buffer is empty");
364 return;
365 }
366 ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
367 process_sp = m_process_wp.lock();
368 if (process_sp)
369 {
370 process_sp->WriteMemory(process_address, bytes, size, error);
371 if (!error.Success())
372 return;
373 }
374 break;
375 case eAllocationPolicyProcessOnly:
376 process_sp = m_process_wp.lock();
377 if (process_sp)
378 {
379 process_sp->WriteMemory(process_address, bytes, size, error);
380 if (!error.Success())
381 return;
382 }
383 break;
384 }
385
386 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
387 {
388 log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
389 (uint64_t)process_address,
390 (uint64_t)bytes,
391 (uint64_t)size,
392 (uint64_t)allocation.m_process_start,
393 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
394 }
395}
396
397void
Sean Callanan35005f72013-04-12 18:10:34 +0000398IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
399{
400 if (size == UINT32_MAX)
401 size = scalar.GetByteSize();
402
403 if (size > 0)
404 {
405 uint8_t buf[32];
406 const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
407 if (mem_size > 0)
408 {
409 return WriteMemory(process_address, buf, mem_size, error);
410 }
411 else
412 {
413 error.SetErrorToGenericError();
414 error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
415 }
416 }
417 else
418 {
419 error.SetErrorToGenericError();
420 error.SetErrorString ("Couldn't write scalar: its size was zero");
421 }
422 return;
423}
424
425void
Sean Callananf8043fa2013-04-12 21:40:34 +0000426IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
427{
428 Scalar scalar(address);
429
430 WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
431}
432
433
434void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000435IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
436{
437 AllocationMap::iterator iter = FindAllocation(process_address, size);
438
439 if (iter == m_allocations.end())
440 {
441 error.SetErrorToGenericError();
442 error.SetErrorString("Couldn't read: no allocation contains the target range");
443 return;
444 }
445
446 Allocation &allocation = iter->second;
447
448 uint64_t offset = process_address - allocation.m_process_start;
449
450 lldb::ProcessSP process_sp;
451
452 switch (allocation.m_policy)
453 {
454 default:
455 error.SetErrorToGenericError();
456 error.SetErrorString("Couldn't read: invalid allocation policy");
457 return;
458 case eAllocationPolicyHostOnly:
459 if (!allocation.m_data)
460 {
461 error.SetErrorToGenericError();
462 error.SetErrorString("Couldn't read: data buffer is empty");
463 return;
464 }
465 ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
466 break;
467 case eAllocationPolicyMirror:
468 process_sp = m_process_wp.lock();
469 if (process_sp)
470 {
471 process_sp->ReadMemory(process_address, bytes, size, error);
472 if (!error.Success())
473 return;
474 }
475 else
476 {
477 if (!allocation.m_data)
478 {
479 error.SetErrorToGenericError();
480 error.SetErrorString("Couldn't read: data buffer is empty");
481 return;
482 }
483 ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
484 }
485 break;
486 case eAllocationPolicyProcessOnly:
487 process_sp = m_process_wp.lock();
488 if (process_sp)
489 {
490 process_sp->ReadMemory(process_address, bytes, size, error);
491 if (!error.Success())
492 return;
493 }
494 break;
495 }
496
497 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
498 {
499 log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
500 (uint64_t)process_address,
501 (uint64_t)bytes,
502 (uint64_t)size,
503 (uint64_t)allocation.m_process_start,
504 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
505 }
506}
Sean Callanan35005f72013-04-12 18:10:34 +0000507
508void
509IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
510{
511 if (size > 0)
512 {
513 DataBufferHeap buf(size, 0);
514 ReadMemory(buf.GetBytes(), process_address, size, error);
515
516 if (!error.Success())
517 return;
518
519 DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
520
521 lldb::offset_t offset = 0;
522
523 switch (size)
524 {
525 default:
526 error.SetErrorToGenericError();
527 error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size);
528 return;
529 case 1: scalar = extractor.GetU8(&offset); break;
530 case 2: scalar = extractor.GetU16(&offset); break;
531 case 4: scalar = extractor.GetU32(&offset); break;
532 case 8: scalar = extractor.GetU64(&offset); break;
533 }
534 }
535 else
536 {
537 error.SetErrorToGenericError();
538 error.SetErrorString ("Couldn't write scalar: its size was zero");
539 }
540 return;
541}
542