blob: a4fe7a9683799d673ccac807f94b7b08e88b8306 [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();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000031
Sean Callanan5a1af4e2013-04-05 02:22:57 +000032 if (process_sp)
33 {
Sean Callananbb777042013-05-16 17:30:37 +000034 AllocationMap::iterator iter;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000035
Sean Callananbb777042013-05-16 17:30:37 +000036 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();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000054
Sean Callananbb9945f2013-04-19 01:51:24 +000055 lldb::addr_t ret = LLDB_INVALID_ADDRESS;
Zachary Turner3ddcd312014-07-09 16:42:27 +000056 if (size == 0)
57 return ret;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000058
Sean Callananad7cc462013-06-17 21:19:31 +000059 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
Sean Callanandf565402013-04-27 02:19:33 +000060 {
61 Error alloc_error;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000062
Sean Callanandf565402013-04-27 02:19:33 +000063 ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000064
Sean Callanandf565402013-04-27 02:19:33 +000065 if (!alloc_error.Success())
66 return LLDB_INVALID_ADDRESS;
67 else
68 return ret;
69 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000070
Zachary Turner3ddcd312014-07-09 16:42:27 +000071 ret = 0;
72 if (!m_allocations.empty())
Sean Callanan5a1af4e2013-04-05 02:22:57 +000073 {
Zachary Turner3ddcd312014-07-09 16:42:27 +000074 auto back = m_allocations.rbegin();
75 lldb::addr_t addr = back->first;
76 size_t alloc_size = back->second.m_size;
77 ret = llvm::RoundUpToAlignment(addr+alloc_size, 4096);
Sean Callanan5a1af4e2013-04-05 02:22:57 +000078 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000079
Sean Callananbb9945f2013-04-19 01:51:24 +000080 return ret;
Sean Callanan5a1af4e2013-04-05 02:22:57 +000081}
82
83IRMemoryMap::AllocationMap::iterator
84IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
85{
Sean Callanan1582ee62013-04-18 22:06:33 +000086 if (addr == LLDB_INVALID_ADDRESS)
87 return m_allocations.end();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000088
Sean Callanan5a1af4e2013-04-05 02:22:57 +000089 AllocationMap::iterator iter = m_allocations.lower_bound (addr);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000090
Sean Callanan14b1bae2013-04-16 23:25:35 +000091 if (iter == m_allocations.end() ||
92 iter->first > addr)
Sean Callanan5a1af4e2013-04-05 02:22:57 +000093 {
94 if (iter == m_allocations.begin())
95 return m_allocations.end();
96 iter--;
97 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000098
Sean Callanan5a1af4e2013-04-05 02:22:57 +000099 if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
100 return iter;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000101
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000102 return m_allocations.end();
103}
104
Sean Callananbb9945f2013-04-19 01:51:24 +0000105bool
Zachary Turner15362442014-06-25 18:37:19 +0000106IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const
Sean Callananbb9945f2013-04-19 01:51:24 +0000107{
108 if (addr == LLDB_INVALID_ADDRESS)
109 return false;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000110
Zachary Turner15362442014-06-25 18:37:19 +0000111 AllocationMap::const_iterator iter = m_allocations.lower_bound (addr);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000112
Zachary Turner15362442014-06-25 18:37:19 +0000113 // Since we only know that the returned interval begins at a location greater than or
114 // equal to where the given interval begins, it's possible that the given interval
115 // intersects either the returned interval or the previous interval. Thus, we need to
116 // check both. Note that we only need to check these two intervals. Since all intervals
117 // are disjoint it is not possible that an adjacent interval does not intersect, but a
118 // non-adjacent interval does intersect.
119 if (iter != m_allocations.end()) {
Zachary Turnercfcd7912014-06-25 18:40:58 +0000120 if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
Sean Callananbb9945f2013-04-19 01:51:24 +0000121 return true;
Sean Callananbb9945f2013-04-19 01:51:24 +0000122 }
Zachary Turner15362442014-06-25 18:37:19 +0000123
124 if (iter != m_allocations.begin()) {
125 --iter;
Zachary Turnercfcd7912014-06-25 18:40:58 +0000126 if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
Zachary Turner15362442014-06-25 18:37:19 +0000127 return true;
128 }
129
Sean Callananbb9945f2013-04-19 01:51:24 +0000130 return false;
131}
132
Zachary Turner15362442014-06-25 18:37:19 +0000133bool
134IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) {
135 // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy
136 // A<B and X<Y are the following:
137 // A B X Y
138 // A X B Y (intersects)
139 // A X Y B (intersects)
140 // X A B Y (intersects)
141 // X A Y B (intersects)
142 // X Y A B
143 // The first is B <= X, and the last is Y <= A.
144 // So the condition is !(B <= X || Y <= A)), or (X < B && A < Y)
145 return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
146}
147
Sean Callanan35005f72013-04-12 18:10:34 +0000148lldb::ByteOrder
149IRMemoryMap::GetByteOrder()
150{
151 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000152
Sean Callanan35005f72013-04-12 18:10:34 +0000153 if (process_sp)
154 return process_sp->GetByteOrder();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000155
Sean Callanan35005f72013-04-12 18:10:34 +0000156 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000157
Sean Callanan35005f72013-04-12 18:10:34 +0000158 if (target_sp)
Sean Callanan08052af2013-04-17 07:50:58 +0000159 return target_sp->GetArchitecture().GetByteOrder();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000160
Sean Callanan35005f72013-04-12 18:10:34 +0000161 return lldb::eByteOrderInvalid;
162}
163
164uint32_t
165IRMemoryMap::GetAddressByteSize()
166{
167 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000168
Sean Callanan35005f72013-04-12 18:10:34 +0000169 if (process_sp)
170 return process_sp->GetAddressByteSize();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000171
Sean Callanan35005f72013-04-12 18:10:34 +0000172 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000173
Sean Callanan35005f72013-04-12 18:10:34 +0000174 if (target_sp)
Sean Callanan08052af2013-04-17 07:50:58 +0000175 return target_sp->GetArchitecture().GetAddressByteSize();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000176
Sean Callanan35005f72013-04-12 18:10:34 +0000177 return UINT32_MAX;
178}
179
180ExecutionContextScope *
Greg Clayton23f8c952014-03-24 23:10:19 +0000181IRMemoryMap::GetBestExecutionContextScope() const
Sean Callanan35005f72013-04-12 18:10:34 +0000182{
183 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000184
Sean Callanan35005f72013-04-12 18:10:34 +0000185 if (process_sp)
186 return process_sp.get();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000187
Sean Callanan35005f72013-04-12 18:10:34 +0000188 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000189
Sean Callanan35005f72013-04-12 18:10:34 +0000190 if (target_sp)
191 return target_sp.get();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000192
Sean Callanan35005f72013-04-12 18:10:34 +0000193 return NULL;
194}
195
Sean Callanand2562502013-04-19 17:44:40 +0000196IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
197 lldb::addr_t process_start,
198 size_t size,
199 uint32_t permissions,
200 uint8_t alignment,
Michael Sartain6fea7792013-08-06 22:21:08 +0000201 AllocationPolicy policy) :
202 m_process_alloc (process_alloc),
203 m_process_start (process_start),
204 m_size (size),
205 m_permissions (permissions),
206 m_alignment (alignment),
207 m_policy (policy),
208 m_leak (false)
Sean Callanand2562502013-04-19 17:44:40 +0000209{
Sean Callanand2562502013-04-19 17:44:40 +0000210 switch (policy)
211 {
212 default:
213 assert (0 && "We cannot reach this!");
214 case eAllocationPolicyHostOnly:
215 m_data.SetByteSize(size);
216 memset(m_data.GetBytes(), 0, size);
217 break;
218 case eAllocationPolicyProcessOnly:
219 break;
220 case eAllocationPolicyMirror:
221 m_data.SetByteSize(size);
222 memset(m_data.GetBytes(), 0, size);
223 break;
224 }
225}
226
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000227lldb::addr_t
228IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
229{
Todd Fialaaf245d12014-06-30 21:05:18 +0000230 lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan08052af2013-04-17 07:50:58 +0000231 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000232
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000233 lldb::ProcessSP process_sp;
234 lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
235 lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
Matt Kopec750dcc32013-04-26 17:48:01 +0000236
237 size_t alignment_mask = alignment - 1;
238 size_t allocation_size;
239
240 if (size == 0)
241 allocation_size = alignment;
242 else
243 allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000244
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000245 switch (policy)
246 {
247 default:
248 error.SetErrorToGenericError();
249 error.SetErrorString("Couldn't malloc: invalid allocation policy");
250 return LLDB_INVALID_ADDRESS;
251 case eAllocationPolicyHostOnly:
252 allocation_address = FindSpace(allocation_size);
253 if (allocation_address == LLDB_INVALID_ADDRESS)
254 {
255 error.SetErrorToGenericError();
256 error.SetErrorString("Couldn't malloc: address space is full");
257 return LLDB_INVALID_ADDRESS;
258 }
259 break;
260 case eAllocationPolicyMirror:
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000261 process_sp = m_process_wp.lock();
Todd Fialaaf245d12014-06-30 21:05:18 +0000262 if (log)
263 log->Printf ("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t) process_sp.get (), process_sp && process_sp->CanJIT () ? "true" : "false", process_sp && process_sp->IsAlive () ? "true" : "false");
Sean Callananad7cc462013-06-17 21:19:31 +0000264 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000265 {
266 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
267 if (!error.Success())
268 return LLDB_INVALID_ADDRESS;
269 }
270 else
271 {
Todd Fialaaf245d12014-06-30 21:05:18 +0000272 if (log)
273 log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__);
Sean Callananbb9945f2013-04-19 01:51:24 +0000274 policy = eAllocationPolicyHostOnly;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000275 allocation_address = FindSpace(allocation_size);
276 if (allocation_address == LLDB_INVALID_ADDRESS)
277 {
278 error.SetErrorToGenericError();
279 error.SetErrorString("Couldn't malloc: address space is full");
280 return LLDB_INVALID_ADDRESS;
281 }
282 }
283 break;
284 case eAllocationPolicyProcessOnly:
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000285 process_sp = m_process_wp.lock();
286 if (process_sp)
287 {
Sean Callananad7cc462013-06-17 21:19:31 +0000288 if (process_sp->CanJIT() && process_sp->IsAlive())
Sean Callananbb9945f2013-04-19 01:51:24 +0000289 {
290 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
291 if (!error.Success())
292 return LLDB_INVALID_ADDRESS;
293 }
294 else
295 {
296 error.SetErrorToGenericError();
297 error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000298 return LLDB_INVALID_ADDRESS;
Sean Callananbb9945f2013-04-19 01:51:24 +0000299 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000300 }
301 else
302 {
303 error.SetErrorToGenericError();
304 error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
305 return LLDB_INVALID_ADDRESS;
306 }
307 break;
308 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000309
310
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000311 lldb::addr_t mask = alignment - 1;
312 aligned_address = (allocation_address + mask) & (~mask);
313
Sean Callanand2562502013-04-19 17:44:40 +0000314 m_allocations[aligned_address] = Allocation(allocation_address,
315 aligned_address,
Matt Kopec750dcc32013-04-26 17:48:01 +0000316 allocation_size,
Sean Callanand2562502013-04-19 17:44:40 +0000317 permissions,
318 alignment,
319 policy);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000320
Todd Fialaaf245d12014-06-30 21:05:18 +0000321 if (log)
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000322 {
323 const char * policy_string;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000324
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000325 switch (policy)
326 {
327 default:
328 policy_string = "<invalid policy>";
329 break;
330 case eAllocationPolicyHostOnly:
331 policy_string = "eAllocationPolicyHostOnly";
332 break;
333 case eAllocationPolicyProcessOnly:
334 policy_string = "eAllocationPolicyProcessOnly";
335 break;
336 case eAllocationPolicyMirror:
337 policy_string = "eAllocationPolicyMirror";
338 break;
339 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000340
Matt Kopecef143712013-06-03 18:00:07 +0000341 log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
Matt Kopec750dcc32013-04-26 17:48:01 +0000342 (uint64_t)allocation_size,
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000343 (uint64_t)alignment,
344 (uint64_t)permissions,
345 policy_string,
346 aligned_address);
347 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000348
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000349 return aligned_address;
350}
351
352void
Sean Callananfbf5c682013-05-22 22:49:06 +0000353IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
354{
355 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000356
Sean Callananfbf5c682013-05-22 22:49:06 +0000357 AllocationMap::iterator iter = m_allocations.find(process_address);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000358
Sean Callananfbf5c682013-05-22 22:49:06 +0000359 if (iter == m_allocations.end())
360 {
361 error.SetErrorToGenericError();
362 error.SetErrorString("Couldn't leak: allocation doesn't exist");
363 return;
364 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000365
Sean Callananfbf5c682013-05-22 22:49:06 +0000366 Allocation &allocation = iter->second;
367
368 allocation.m_leak = true;
369}
370
371void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000372IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
373{
Sean Callanan08052af2013-04-17 07:50:58 +0000374 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000375
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000376 AllocationMap::iterator iter = m_allocations.find(process_address);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000377
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000378 if (iter == m_allocations.end())
379 {
380 error.SetErrorToGenericError();
381 error.SetErrorString("Couldn't free: allocation doesn't exist");
382 return;
383 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000384
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000385 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000386
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000387 switch (allocation.m_policy)
388 {
389 default:
390 case eAllocationPolicyHostOnly:
Sean Callanandf565402013-04-27 02:19:33 +0000391 {
392 lldb::ProcessSP process_sp = m_process_wp.lock();
Sean Callananbb777042013-05-16 17:30:37 +0000393 if (process_sp)
394 {
Sean Callananad7cc462013-06-17 21:19:31 +0000395 if (process_sp->CanJIT() && process_sp->IsAlive())
Sean Callananbb777042013-05-16 17:30:37 +0000396 process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
Sean Callananbb777042013-05-16 17:30:37 +0000397 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000398
Sean Callanandf565402013-04-27 02:19:33 +0000399 break;
400 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000401 case eAllocationPolicyMirror:
402 case eAllocationPolicyProcessOnly:
Sean Callanandf565402013-04-27 02:19:33 +0000403 {
404 lldb::ProcessSP process_sp = m_process_wp.lock();
405 if (process_sp)
406 process_sp->DeallocateMemory(allocation.m_process_alloc);
407 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000408 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000409
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000410 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000411 {
Matt Kopecef143712013-06-03 18:00:07 +0000412 log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000413 (uint64_t)process_address,
414 iter->second.m_process_start,
415 iter->second.m_process_start + iter->second.m_size);
416 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000417
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000418 m_allocations.erase(iter);
419}
420
421void
422IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
423{
Sean Callanan08052af2013-04-17 07:50:58 +0000424 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000425
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000426 AllocationMap::iterator iter = FindAllocation(process_address, size);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000427
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000428 if (iter == m_allocations.end())
429 {
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000430 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000431
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000432 if (process_sp)
433 {
434 process_sp->WriteMemory(process_address, bytes, size, error);
435 return;
436 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000437
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000438 error.SetErrorToGenericError();
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000439 error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000440 return;
441 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000442
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000443 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000444
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000445 uint64_t offset = process_address - allocation.m_process_start;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000446
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000447 lldb::ProcessSP process_sp;
448
449 switch (allocation.m_policy)
450 {
451 default:
452 error.SetErrorToGenericError();
453 error.SetErrorString("Couldn't write: invalid allocation policy");
454 return;
455 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000456 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000457 {
458 error.SetErrorToGenericError();
459 error.SetErrorString("Couldn't write: data buffer is empty");
460 return;
461 }
Sean Callanand2562502013-04-19 17:44:40 +0000462 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000463 break;
464 case eAllocationPolicyMirror:
Sean Callanand2562502013-04-19 17:44:40 +0000465 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000466 {
467 error.SetErrorToGenericError();
468 error.SetErrorString("Couldn't write: data buffer is empty");
469 return;
470 }
Sean Callanand2562502013-04-19 17:44:40 +0000471 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000472 process_sp = m_process_wp.lock();
473 if (process_sp)
474 {
475 process_sp->WriteMemory(process_address, bytes, size, error);
476 if (!error.Success())
477 return;
478 }
479 break;
480 case eAllocationPolicyProcessOnly:
481 process_sp = m_process_wp.lock();
482 if (process_sp)
483 {
484 process_sp->WriteMemory(process_address, bytes, size, error);
485 if (!error.Success())
486 return;
487 }
488 break;
489 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000490
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000491 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000492 {
Matt Kopecef143712013-06-03 18:00:07 +0000493 log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000494 (uint64_t)process_address,
495 (uint64_t)bytes,
496 (uint64_t)size,
497 (uint64_t)allocation.m_process_start,
498 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
499 }
500}
501
502void
Sean Callanan35005f72013-04-12 18:10:34 +0000503IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
Sean Callanan08052af2013-04-17 07:50:58 +0000504{
505 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000506
Sean Callanan35005f72013-04-12 18:10:34 +0000507 if (size == UINT32_MAX)
508 size = scalar.GetByteSize();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000509
Sean Callanan35005f72013-04-12 18:10:34 +0000510 if (size > 0)
511 {
512 uint8_t buf[32];
513 const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
514 if (mem_size > 0)
515 {
516 return WriteMemory(process_address, buf, mem_size, error);
517 }
518 else
519 {
520 error.SetErrorToGenericError();
521 error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
522 }
523 }
524 else
525 {
526 error.SetErrorToGenericError();
527 error.SetErrorString ("Couldn't write scalar: its size was zero");
528 }
529 return;
530}
531
532void
Sean Callananf8043fa2013-04-12 21:40:34 +0000533IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
534{
Sean Callanan08052af2013-04-17 07:50:58 +0000535 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000536
Sean Callananf8043fa2013-04-12 21:40:34 +0000537 Scalar scalar(address);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000538
Sean Callananf8043fa2013-04-12 21:40:34 +0000539 WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
540}
541
Sean Callananf8043fa2013-04-12 21:40:34 +0000542void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000543IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
544{
Sean Callanan08052af2013-04-17 07:50:58 +0000545 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000546
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000547 AllocationMap::iterator iter = FindAllocation(process_address, size);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000548
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000549 if (iter == m_allocations.end())
550 {
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000551 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000552
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000553 if (process_sp)
554 {
555 process_sp->ReadMemory(process_address, bytes, size, error);
556 return;
557 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000558
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000559 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000560
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000561 if (target_sp)
562 {
563 Address absolute_address(process_address);
564 target_sp->ReadMemory(absolute_address, false, bytes, size, error);
565 return;
566 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000567
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000568 error.SetErrorToGenericError();
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000569 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 +0000570 return;
571 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000572
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000573 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000574
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000575 uint64_t offset = process_address - allocation.m_process_start;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000576
Sean Callanan9bbf3cd2014-03-04 21:56:11 +0000577 if (offset > allocation.m_size)
578 {
579 error.SetErrorToGenericError();
580 error.SetErrorString("Couldn't read: data is not in the allocation");
581 return;
582 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000583
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000584 lldb::ProcessSP process_sp;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000585
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000586 switch (allocation.m_policy)
587 {
588 default:
589 error.SetErrorToGenericError();
590 error.SetErrorString("Couldn't read: invalid allocation policy");
591 return;
592 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000593 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000594 {
595 error.SetErrorToGenericError();
596 error.SetErrorString("Couldn't read: data buffer is empty");
597 return;
598 }
Sean Callanan9bbf3cd2014-03-04 21:56:11 +0000599 if (allocation.m_data.GetByteSize() < offset + size)
600 {
601 error.SetErrorToGenericError();
602 error.SetErrorString("Couldn't read: not enough underlying data");
603 return;
604 }
605
Sean Callanand2562502013-04-19 17:44:40 +0000606 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000607 break;
608 case eAllocationPolicyMirror:
609 process_sp = m_process_wp.lock();
610 if (process_sp)
611 {
612 process_sp->ReadMemory(process_address, bytes, size, error);
613 if (!error.Success())
614 return;
615 }
616 else
617 {
Sean Callanand2562502013-04-19 17:44:40 +0000618 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000619 {
620 error.SetErrorToGenericError();
621 error.SetErrorString("Couldn't read: data buffer is empty");
622 return;
623 }
Sean Callanand2562502013-04-19 17:44:40 +0000624 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000625 }
626 break;
627 case eAllocationPolicyProcessOnly:
628 process_sp = m_process_wp.lock();
629 if (process_sp)
630 {
631 process_sp->ReadMemory(process_address, bytes, size, error);
632 if (!error.Success())
633 return;
634 }
635 break;
636 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000637
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000638 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
639 {
Matt Kopecef143712013-06-03 18:00:07 +0000640 log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000641 (uint64_t)process_address,
642 (uint64_t)bytes,
643 (uint64_t)size,
644 (uint64_t)allocation.m_process_start,
645 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
646 }
647}
Sean Callanan35005f72013-04-12 18:10:34 +0000648
649void
650IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
Sean Callanan08052af2013-04-17 07:50:58 +0000651{
652 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000653
Sean Callanan35005f72013-04-12 18:10:34 +0000654 if (size > 0)
655 {
656 DataBufferHeap buf(size, 0);
657 ReadMemory(buf.GetBytes(), process_address, size, error);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000658
Sean Callanan35005f72013-04-12 18:10:34 +0000659 if (!error.Success())
660 return;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000661
Sean Callanan35005f72013-04-12 18:10:34 +0000662 DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000663
Sean Callanan35005f72013-04-12 18:10:34 +0000664 lldb::offset_t offset = 0;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000665
Sean Callanan35005f72013-04-12 18:10:34 +0000666 switch (size)
667 {
668 default:
669 error.SetErrorToGenericError();
Greg Claytone86cef62013-06-04 21:30:42 +0000670 error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
Sean Callanan35005f72013-04-12 18:10:34 +0000671 return;
672 case 1: scalar = extractor.GetU8(&offset); break;
673 case 2: scalar = extractor.GetU16(&offset); break;
674 case 4: scalar = extractor.GetU32(&offset); break;
675 case 8: scalar = extractor.GetU64(&offset); break;
676 }
677 }
678 else
679 {
680 error.SetErrorToGenericError();
Sean Callanan458ae1c2013-04-13 02:06:42 +0000681 error.SetErrorString ("Couldn't read scalar: its size was zero");
Sean Callanan35005f72013-04-12 18:10:34 +0000682 }
683 return;
684}
685
Sean Callanan458ae1c2013-04-13 02:06:42 +0000686void
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000687IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
688{
Sean Callanan08052af2013-04-17 07:50:58 +0000689 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000690
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000691 Scalar pointer_scalar;
692 ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000693
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000694 if (!error.Success())
695 return;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000696
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000697 *address = pointer_scalar.ULongLong();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000698
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000699 return;
700}
701
702void
Sean Callanan458ae1c2013-04-13 02:06:42 +0000703IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
704{
Sean Callanan08052af2013-04-17 07:50:58 +0000705 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000706
Sean Callanan458ae1c2013-04-13 02:06:42 +0000707 if (size > 0)
708 {
709 AllocationMap::iterator iter = FindAllocation(process_address, size);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000710
Sean Callanan458ae1c2013-04-13 02:06:42 +0000711 if (iter == m_allocations.end())
712 {
713 error.SetErrorToGenericError();
Matt Kopecef143712013-06-03 18:00:07 +0000714 error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
Sean Callanan458ae1c2013-04-13 02:06:42 +0000715 return;
716 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000717
Sean Callanan458ae1c2013-04-13 02:06:42 +0000718 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000719
Sean Callanan458ae1c2013-04-13 02:06:42 +0000720 switch (allocation.m_policy)
721 {
722 default:
723 error.SetErrorToGenericError();
724 error.SetErrorString("Couldn't get memory data: invalid allocation policy");
725 return;
726 case eAllocationPolicyProcessOnly:
727 error.SetErrorToGenericError();
728 error.SetErrorString("Couldn't get memory data: memory is only in the target");
729 return;
Sean Callanan458ae1c2013-04-13 02:06:42 +0000730 case eAllocationPolicyMirror:
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000731 {
732 lldb::ProcessSP process_sp = m_process_wp.lock();
733
Sean Callanand2562502013-04-19 17:44:40 +0000734 if (!allocation.m_data.GetByteSize())
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000735 {
736 error.SetErrorToGenericError();
737 error.SetErrorString("Couldn't get memory data: data buffer is empty");
738 return;
739 }
740 if (process_sp)
741 {
Sean Callanand2562502013-04-19 17:44:40 +0000742 process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000743 if (!error.Success())
744 return;
745 uint64_t offset = process_address - allocation.m_process_start;
Sean Callanand2562502013-04-19 17:44:40 +0000746 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000747 return;
748 }
749 }
750 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000751 if (!allocation.m_data.GetByteSize())
Sean Callanan458ae1c2013-04-13 02:06:42 +0000752 {
753 error.SetErrorToGenericError();
754 error.SetErrorString("Couldn't get memory data: data buffer is empty");
755 return;
756 }
757 uint64_t offset = process_address - allocation.m_process_start;
Sean Callanand2562502013-04-19 17:44:40 +0000758 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
Sean Callanan458ae1c2013-04-13 02:06:42 +0000759 return;
760 }
761 }
762 else
763 {
764 error.SetErrorToGenericError();
765 error.SetErrorString ("Couldn't get memory data: its size was zero");
766 return;
767 }
768}