VirtualBox

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

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

DBGFR3MemScan: Fixed crash on 32-bit hosts.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.9 KB
Line 
1/* $Id: DBGFMem.cpp 15997 2009-01-16 16:13:23Z 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
34
35
36/**
37 * Scan guest memory for an exact byte string.
38 *
39 * @returns VBox status code.
40 * @param pVM The VM handle.
41 * @param pAddress Where to store the mixed address.
42 * @param pcbRange The number of bytes to scan. Passed as a pointer because
43 * it may be 64-bit.
44 * @param pabNeedle What to search for - exact search.
45 * @param cbNeedle Size of the search byte string.
46 * @param pHitAddress Where to put the address of the first hit.
47 */
48static DECLCALLBACK(int) dbgfR3MemScan(PVM pVM, PCDBGFADDRESS pAddress, PCRTGCUINTPTR pcbRange, const uint8_t *pabNeedle, size_t cbNeedle,
49 PDBGFADDRESS pHitAddress)
50{
51 /*
52 * Validate the input we use, PGM does the rest.
53 */
54 RTGCUINTPTR cbRange = *pcbRange;
55 if (!DBGFR3AddrIsValid(pVM, pAddress))
56 return VERR_INVALID_POINTER;
57 if (!VALID_PTR(pHitAddress))
58 return VERR_INVALID_POINTER;
59 if (DBGFADDRESS_IS_HMA(pAddress))
60 return VERR_INVALID_POINTER;
61
62 /*
63 * Select DBGF worker by addressing mode.
64 */
65 int rc;
66 PGMMODE enmMode = PGMGetGuestMode(pVM);
67 if ( enmMode == PGMMODE_REAL
68 || enmMode == PGMMODE_PROTECTED
69 || DBGFADDRESS_IS_PHYS(pAddress)
70 )
71 {
72 RTGCPHYS PhysHit;
73 rc = PGMR3DbgScanPhysical(pVM, pAddress->FlatPtr, cbRange, pabNeedle, cbNeedle, &PhysHit);
74 if (RT_SUCCESS(rc))
75 DBGFR3AddrFromPhys(pVM, pHitAddress, PhysHit);
76 }
77 else
78 {
79#if GC_ARCH_BITS > 32
80 if ( ( pAddress->FlatPtr >= _4G
81 || pAddress->FlatPtr + cbRange > _4G)
82 && enmMode != PGMMODE_AMD64
83 && enmMode != PGMMODE_AMD64_NX)
84 return VERR_DBGF_MEM_NOT_FOUND;
85#endif
86 RTGCUINTPTR GCPtrHit;
87 rc = PGMR3DbgScanVirtual(pVM, pAddress->FlatPtr, cbRange, pabNeedle, cbNeedle, &GCPtrHit);
88 if (RT_SUCCESS(rc))
89 DBGFR3AddrFromFlat(pVM, pHitAddress, GCPtrHit);
90 }
91
92 return rc;
93}
94
95
96/**
97 * Scan guest memory for an exact byte string.
98 *
99 * @returns VBox status codes:
100 * @retval VINF_SUCCESS and *pGCPtrHit on success.
101 * @retval VERR_DBGF_MEM_NOT_FOUND if not found.
102 * @retval VERR_INVALID_POINTER if any of the pointer arguments are invalid.
103 * @retval VERR_INVALID_ARGUMENT if any other arguments are invalid.
104 *
105 * @param pVM The VM handle.
106 * @param pAddress Where to store the mixed address.
107 * @param cbRange The number of bytes to scan.
108 * @param pabNeedle What to search for - exact search.
109 * @param cbNeedle Size of the search byte string.
110 * @param pHitAddress Where to put the address of the first hit.
111 *
112 * @thread Any thread.
113 */
114VMMR3DECL(int) DBGFR3MemScan(PVM pVM, PCDBGFADDRESS pAddress, RTGCUINTPTR cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress)
115{
116 PVMREQ pReq;
117 int rc = VMR3ReqCall(pVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, (PFNRT)dbgfR3MemScan, 6,
118 pVM, pAddress, &cbRange, pabNeedle, cbNeedle, pHitAddress);
119 if (RT_SUCCESS(rc))
120 rc = pReq->iStatus;
121 VMR3ReqFree(pReq);
122
123 return rc;
124}
125
126
127/**
128 * Read guest memory.
129 *
130 * @returns VBox status code.
131 * @param pVM Pointer to the shared VM structure.
132 * @param pAddress Where to start reading.
133 * @param pvBuf Where to store the data we've read.
134 * @param cbRead The number of bytes to read.
135 */
136static DECLCALLBACK(int) dbgfR3MemRead(PVM pVM, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead)
137{
138 /*
139 * Validate the input we use, PGM does the rest.
140 */
141 if (!DBGFR3AddrIsValid(pVM, pAddress))
142 return VERR_INVALID_POINTER;
143 if (!VALID_PTR(pvBuf))
144 return VERR_INVALID_POINTER;
145 if (DBGFADDRESS_IS_HMA(pAddress))
146 return VERR_INVALID_POINTER;
147
148 /*
149 * Select DBGF worker by addressing mode.
150 */
151 int rc;
152 PGMMODE enmMode = PGMGetGuestMode(pVM);
153 if ( enmMode == PGMMODE_REAL
154 || enmMode == PGMMODE_PROTECTED
155 || DBGFADDRESS_IS_PHYS(pAddress) )
156 rc = PGMPhysSimpleReadGCPhys(pVM, pvBuf, pAddress->FlatPtr, cbRead);
157 else
158 {
159#if GC_ARCH_BITS > 32
160 if ( ( pAddress->FlatPtr >= _4G
161 || pAddress->FlatPtr + cbRead > _4G)
162 && enmMode != PGMMODE_AMD64
163 && enmMode != PGMMODE_AMD64_NX)
164 return VERR_PAGE_TABLE_NOT_PRESENT;
165#endif
166 rc = PGMPhysSimpleReadGCPtr(pVM, pvBuf, pAddress->FlatPtr, cbRead);
167 }
168 return rc;
169}
170
171
172/**
173 * Read guest memory.
174 *
175 * @returns VBox status code.
176 * @param pVM Pointer to the shared VM structure.
177 * @param pAddress Where to start reading.
178 * @param pvBuf Where to store the data we've read.
179 * @param cbRead The number of bytes to read.
180 */
181VMMR3DECL(int) DBGFR3MemRead(PVM pVM, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead)
182{
183 PVMREQ pReq;
184 int rc = VMR3ReqCallU(pVM->pUVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)dbgfR3MemRead, 4,
185 pVM, pAddress, pvBuf, cbRead);
186 if (RT_SUCCESS(rc))
187 rc = pReq->iStatus;
188 VMR3ReqFree(pReq);
189
190 return rc;
191}
192
193
194/**
195 * Read a zero terminated string from guest memory.
196 *
197 * @returns VBox status code.
198 * @param pVM Pointer to the shared VM structure.
199 * @param pAddress Where to start reading.
200 * @param pszBuf Where to store the string.
201 * @param cchBuf The size of the buffer.
202 */
203static DECLCALLBACK(int) dbgfR3MemReadString(PVM pVM, PCDBGFADDRESS pAddress, char *pszBuf, size_t cchBuf)
204{
205 /*
206 * Validate the input we use, PGM does the rest.
207 */
208 if (!DBGFR3AddrIsValid(pVM, pAddress))
209 return VERR_INVALID_POINTER;
210 if (!VALID_PTR(pszBuf))
211 return VERR_INVALID_POINTER;
212 if (DBGFADDRESS_IS_HMA(pAddress))
213 return VERR_INVALID_POINTER;
214
215 /*
216 * Select DBGF worker by addressing mode.
217 */
218 int rc;
219 PGMMODE enmMode = PGMGetGuestMode(pVM);
220 if ( enmMode == PGMMODE_REAL
221 || enmMode == PGMMODE_PROTECTED
222 || DBGFADDRESS_IS_PHYS(pAddress) )
223 rc = PGMPhysSimpleReadGCPhys(pVM, pszBuf, pAddress->FlatPtr, cchBuf);
224 else
225 {
226#if GC_ARCH_BITS > 32
227 if ( ( pAddress->FlatPtr >= _4G
228 || pAddress->FlatPtr + cchBuf > _4G)
229 && enmMode != PGMMODE_AMD64
230 && enmMode != PGMMODE_AMD64_NX)
231 return VERR_PAGE_TABLE_NOT_PRESENT;
232#endif
233 rc = PGMPhysSimpleReadGCPtr(pVM, pszBuf, pAddress->FlatPtr, cchBuf);
234 }
235
236 /*
237 * Make sure the result is terminated and that overflow is signaled.
238 */
239 if (!memchr(pszBuf, '\0', cchBuf))
240 {
241 pszBuf[cchBuf - 1] = '\0';
242 rc = VINF_BUFFER_OVERFLOW;
243 }
244 /*
245 * Handle partial reads (not perfect).
246 */
247 else if (RT_FAILURE(rc))
248 {
249 if (pszBuf[0])
250 rc = VINF_SUCCESS;
251 }
252
253 return rc;
254}
255
256
257/**
258 * Read a zero terminated string from guest memory.
259 *
260 * @returns VBox status code.
261 * @param pVM Pointer to the shared VM structure.
262 * @param pAddress Where to start reading.
263 * @param pszBuf Where to store the string.
264 * @param cchBuf The size of the buffer.
265 */
266VMMR3DECL(int) DBGFR3MemReadString(PVM pVM, PCDBGFADDRESS pAddress, char *pszBuf, size_t cchBuf)
267{
268 /*
269 * Validate and zero output.
270 */
271 if (!VALID_PTR(pszBuf))
272 return VERR_INVALID_POINTER;
273 if (cchBuf <= 0)
274 return VERR_INVALID_PARAMETER;
275 memset(pszBuf, 0, cchBuf);
276
277 /*
278 * Pass it on to the EMT.
279 */
280 PVMREQ pReq;
281 int rc = VMR3ReqCallU(pVM->pUVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)dbgfR3MemReadString, 4,
282 pVM, pAddress, pszBuf, cchBuf);
283 if (RT_SUCCESS(rc))
284 rc = pReq->iStatus;
285 VMR3ReqFree(pReq);
286
287 return rc;
288}
289
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