VirtualBox

source: vbox/trunk/src/VBox/VMM/DBGFMem.cpp@ 19293

Last change on this file since 19293 was 19293, checked in by vboxsync, 16 years ago

DBGF,VMM: SMP refactoring of the DBGF disassembler code. Changed VMMGetCpu and VMMGetCpuId to return NULL and NIL if the caller isn't an EMT. Renamed VMMGetCpuEx to VMMGetCpuById.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.9 KB
Line 
1/* $Id: DBGFMem.cpp 19293 2009-05-01 16:11:18Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, Memory Methods.
4 */
5
6/*
7 * Copyright (C) 2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DBGF
27#include <VBox/dbgf.h>
28#include <VBox/pgm.h>
29#include "DBGFInternal.h"
30#include <VBox/vm.h>
31#include <VBox/err.h>
32#include <VBox/log.h>
33#include <VBox/mm.h>
34
35
36
37/**
38 * Scan guest memory for an exact byte string.
39 *
40 * @returns VBox status code.
41 * @param pVM The VM handle.
42 * @param idCpu The ID of the CPU context to search in.
43 * @param pAddress Where to store the mixed address.
44 * @param pcbRange The number of bytes to scan. Passed as a pointer because
45 * it may be 64-bit.
46 * @param pabNeedle What to search for - exact search.
47 * @param cbNeedle Size of the search byte string.
48 * @param pHitAddress Where to put the address of the first hit.
49 */
50static DECLCALLBACK(int) dbgfR3MemScan(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, PCRTGCUINTPTR pcbRange,
51 const uint8_t *pabNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress)
52{
53 Assert(idCpu == VMMGetCpuId(pVM));
54
55 /*
56 * Validate the input we use, PGM does the rest.
57 */
58 RTGCUINTPTR cbRange = *pcbRange;
59 if (!DBGFR3AddrIsValid(pVM, pAddress))
60 return VERR_INVALID_POINTER;
61 if (!VALID_PTR(pHitAddress))
62 return VERR_INVALID_POINTER;
63 if (DBGFADDRESS_IS_HMA(pAddress))
64 return VERR_INVALID_POINTER;
65
66 /*
67 * Select DBGF worker by addressing mode.
68 */
69 int rc;
70 PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
71 PGMMODE enmMode = PGMGetGuestMode(pVCpu);
72 if ( enmMode == PGMMODE_REAL
73 || enmMode == PGMMODE_PROTECTED
74 || DBGFADDRESS_IS_PHYS(pAddress)
75 )
76 {
77 RTGCPHYS PhysHit;
78 rc = PGMR3DbgScanPhysical(pVM, pAddress->FlatPtr, cbRange, pabNeedle, cbNeedle, &PhysHit);
79 if (RT_SUCCESS(rc))
80 DBGFR3AddrFromPhys(pVM, pHitAddress, PhysHit);
81 }
82 else
83 {
84#if GC_ARCH_BITS > 32
85 if ( ( pAddress->FlatPtr >= _4G
86 || pAddress->FlatPtr + cbRange > _4G)
87 && enmMode != PGMMODE_AMD64
88 && enmMode != PGMMODE_AMD64_NX)
89 return VERR_DBGF_MEM_NOT_FOUND;
90#endif
91 RTGCUINTPTR GCPtrHit;
92 rc = PGMR3DbgScanVirtual(pVM, pVCpu, pAddress->FlatPtr, cbRange, pabNeedle, cbNeedle, &GCPtrHit);
93 if (RT_SUCCESS(rc))
94 DBGFR3AddrFromFlat(pVM, pHitAddress, GCPtrHit);
95 }
96
97 return rc;
98}
99
100
101/**
102 * Scan guest memory for an exact byte string.
103 *
104 * @returns VBox status codes:
105 * @retval VINF_SUCCESS and *pGCPtrHit on success.
106 * @retval VERR_DBGF_MEM_NOT_FOUND if not found.
107 * @retval VERR_INVALID_POINTER if any of the pointer arguments are invalid.
108 * @retval VERR_INVALID_ARGUMENT if any other arguments are invalid.
109 *
110 * @param pVM The VM handle.
111 * @param idCpu The ID of the CPU context to search in.
112 * @param pAddress Where to store the mixed address.
113 * @param cbRange The number of bytes to scan.
114 * @param pabNeedle What to search for - exact search.
115 * @param cbNeedle Size of the search byte string.
116 * @param pHitAddress Where to put the address of the first hit.
117 *
118 * @thread Any thread.
119 */
120VMMR3DECL(int) DBGFR3MemScan(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, RTGCUINTPTR cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress)
121{
122 AssertReturn(idCpu < pVM->cCPUs, VERR_INVALID_PARAMETER);
123
124 PVMREQ pReq;
125 int rc = VMR3ReqCall(pVM, VMREQDEST_FROM_ID(idCpu), &pReq, RT_INDEFINITE_WAIT,
126 (PFNRT)dbgfR3MemScan, 7, pVM, idCpu, pAddress, &cbRange, pabNeedle, cbNeedle, pHitAddress);
127 if (RT_SUCCESS(rc))
128 rc = pReq->iStatus;
129 VMR3ReqFree(pReq);
130
131 return rc;
132}
133
134
135/**
136 * Read guest memory.
137 *
138 * @returns VBox status code.
139 * @param pVM Pointer to the shared VM structure.
140 * @param pAddress Where to start reading.
141 * @param pvBuf Where to store the data we've read.
142 * @param cbRead The number of bytes to read.
143 */
144static DECLCALLBACK(int) dbgfR3MemRead(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead)
145{
146 Assert(idCpu == VMMGetCpuId(pVM));
147
148 /*
149 * Validate the input we use, PGM does the rest.
150 */
151 if (!DBGFR3AddrIsValid(pVM, pAddress))
152 return VERR_INVALID_POINTER;
153 if (!VALID_PTR(pvBuf))
154 return VERR_INVALID_POINTER;
155
156 /*
157 * HMA is special
158 */
159 int rc;
160 if (DBGFADDRESS_IS_HMA(pAddress))
161 {
162 rc = VERR_INVALID_POINTER;
163 }
164 else
165 {
166 /*
167 * Select DBGF worker by addressing mode.
168 */
169 PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
170 PGMMODE enmMode = PGMGetGuestMode(pVCpu);
171 if ( enmMode == PGMMODE_REAL
172 || enmMode == PGMMODE_PROTECTED
173 || DBGFADDRESS_IS_PHYS(pAddress) )
174 rc = PGMPhysSimpleReadGCPhys(pVM, pvBuf, pAddress->FlatPtr, cbRead);
175 else
176 {
177#if GC_ARCH_BITS > 32
178 if ( ( pAddress->FlatPtr >= _4G
179 || pAddress->FlatPtr + cbRead > _4G)
180 && enmMode != PGMMODE_AMD64
181 && enmMode != PGMMODE_AMD64_NX)
182 return VERR_PAGE_TABLE_NOT_PRESENT;
183#endif
184 rc = PGMPhysSimpleReadGCPtr(pVCpu, pvBuf, pAddress->FlatPtr, cbRead);
185 }
186 }
187 return rc;
188}
189
190
191/**
192 * Read guest memory.
193 *
194 * @returns VBox status code.
195 *
196 * @param pVM Pointer to the shared VM structure.
197 * @param idCpu The ID of the source CPU context (for the address).
198 * @param pAddress Where to start reading.
199 * @param pvBuf Where to store the data we've read.
200 * @param cbRead The number of bytes to read.
201 */
202VMMR3DECL(int) DBGFR3MemRead(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead)
203{
204 AssertReturn(idCpu < pVM->cCPUs, VERR_INVALID_PARAMETER);
205
206 PVMREQ pReq;
207 int rc = VMR3ReqCallU(pVM->pUVM, VMREQDEST_FROM_ID(idCpu), &pReq, RT_INDEFINITE_WAIT, 0,
208 (PFNRT)dbgfR3MemRead, 5, pVM, idCpu, pAddress, pvBuf, cbRead);
209 if (RT_SUCCESS(rc))
210 rc = pReq->iStatus;
211 VMR3ReqFree(pReq);
212
213 return rc;
214}
215
216
217/**
218 * Read a zero terminated string from guest memory.
219 *
220 * @returns VBox status code.
221 *
222 * @param pVM Pointer to the shared VM structure.
223 * @param idCpu The ID of the source CPU context (for the address).
224 * @param pAddress Where to start reading.
225 * @param pszBuf Where to store the string.
226 * @param cchBuf The size of the buffer.
227 */
228static DECLCALLBACK(int) dbgfR3MemReadString(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, char *pszBuf, size_t cchBuf)
229{
230 /*
231 * Validate the input we use, PGM does the rest.
232 */
233 if (!DBGFR3AddrIsValid(pVM, pAddress))
234 return VERR_INVALID_POINTER;
235 if (!VALID_PTR(pszBuf))
236 return VERR_INVALID_POINTER;
237
238 /*
239 * Let dbgfR3MemRead do the job.
240 */
241 int rc = dbgfR3MemRead(pVM, idCpu, pAddress, pszBuf, cchBuf);
242
243 /*
244 * Make sure the result is terminated and that overflow is signaled.
245 * This may look a bit reckless with the rc but, it should be fine.
246 */
247 if (!memchr(pszBuf, '\0', cchBuf))
248 {
249 pszBuf[cchBuf - 1] = '\0';
250 rc = VINF_BUFFER_OVERFLOW;
251 }
252 /*
253 * Handle partial reads (not perfect).
254 */
255 else if (RT_FAILURE(rc))
256 {
257 if (pszBuf[0])
258 rc = VINF_SUCCESS;
259 }
260
261 return rc;
262}
263
264
265/**
266 * Read a zero terminated string from guest memory.
267 *
268 * @returns VBox status code.
269 *
270 * @param pVM Pointer to the shared VM structure.
271 * @param idCpu The ID of the source CPU context (for the address).
272 * @param pAddress Where to start reading.
273 * @param pszBuf Where to store the string.
274 * @param cchBuf The size of the buffer.
275 */
276VMMR3DECL(int) DBGFR3MemReadString(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, char *pszBuf, size_t cchBuf)
277{
278 /*
279 * Validate and zero output.
280 */
281 if (!VALID_PTR(pszBuf))
282 return VERR_INVALID_POINTER;
283 if (cchBuf <= 0)
284 return VERR_INVALID_PARAMETER;
285 memset(pszBuf, 0, cchBuf);
286 AssertReturn(idCpu < pVM->cCPUs, VERR_INVALID_PARAMETER);
287
288 /*
289 * Pass it on to the EMT.
290 */
291 PVMREQ pReq;
292 int rc = VMR3ReqCallU(pVM->pUVM, VMREQDEST_FROM_ID(idCpu), &pReq, RT_INDEFINITE_WAIT, 0,
293 (PFNRT)dbgfR3MemReadString, 5, pVM, idCpu, pAddress, pszBuf, cchBuf);
294 if (RT_SUCCESS(rc))
295 rc = pReq->iStatus;
296 VMR3ReqFree(pReq);
297
298 return rc;
299}
300
301
302/**
303 * Writes guest memory.
304 *
305 * @returns VBox status code.
306 *
307 * @param pVM Pointer to the shared VM structure.
308 * @param idCpu The ID of the target CPU context (for the address).
309 * @param pAddress Where to start writing.
310 * @param pvBuf The data to write.
311 * @param cbRead The number of bytes to write.
312 */
313static DECLCALLBACK(int) dbgfR3MemWrite(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void const *pvBuf, size_t cbWrite)
314{
315 /*
316 * Validate the input we use, PGM does the rest.
317 */
318 if (!DBGFR3AddrIsValid(pVM, pAddress))
319 return VERR_INVALID_POINTER;
320 if (!VALID_PTR(pvBuf))
321 return VERR_INVALID_POINTER;
322
323 /*
324 * HMA is always special.
325 */
326 int rc;
327 if (DBGFADDRESS_IS_HMA(pAddress))
328 {
329 /** @todo write to HMA. */
330 rc = VERR_ACCESS_DENIED;
331 }
332 else
333 {
334 /*
335 * Select PGM function by addressing mode.
336 */
337 PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
338 PGMMODE enmMode = PGMGetGuestMode(pVCpu);
339 if ( enmMode == PGMMODE_REAL
340 || enmMode == PGMMODE_PROTECTED
341 || DBGFADDRESS_IS_PHYS(pAddress) )
342 rc = PGMPhysSimpleWriteGCPhys(pVM, pAddress->FlatPtr, pvBuf, cbWrite);
343 else
344 {
345#if GC_ARCH_BITS > 32
346 if ( ( pAddress->FlatPtr >= _4G
347 || pAddress->FlatPtr + cbWrite > _4G)
348 && enmMode != PGMMODE_AMD64
349 && enmMode != PGMMODE_AMD64_NX)
350 return VERR_PAGE_TABLE_NOT_PRESENT;
351#endif
352 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pAddress->FlatPtr, pvBuf, cbWrite);
353 }
354 }
355 return rc;
356}
357
358
359/**
360 * Read guest memory.
361 *
362 * @returns VBox status code.
363 *
364 * @param pVM Pointer to the shared VM structure.
365 * @param idCpu The ID of the target CPU context (for the address).
366 * @param pAddress Where to start writing.
367 * @param pvBuf The data to write.
368 * @param cbRead The number of bytes to write.
369 */
370VMMR3DECL(int) DBGFR3MemWrite(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void const *pvBuf, size_t cbWrite)
371{
372 AssertReturn(idCpu < pVM->cCPUs, VERR_INVALID_PARAMETER);
373
374 PVMREQ pReq;
375 int rc = VMR3ReqCallU(pVM->pUVM, VMREQDEST_FROM_ID(idCpu), &pReq, RT_INDEFINITE_WAIT, 0,
376 (PFNRT)dbgfR3MemWrite, 5, pVM, idCpu, pAddress, pvBuf, cbWrite);
377 if (RT_SUCCESS(rc))
378 rc = pReq->iStatus;
379 VMR3ReqFree(pReq);
380
381 return rc;
382}
383
384
385
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette