| | 174 | |
|---|
| | 175 | |
|---|
| | 176 | /** |
|---|
| | 177 | * Read a zero terminated string from guest memory. |
|---|
| | 178 | * |
|---|
| | 179 | * @returns VBox status code. |
|---|
| | 180 | * @param pVM Pointer to the shared VM structure. |
|---|
| | 181 | * @param pAddress Where to start reading. |
|---|
| | 182 | * @param pszBuf Where to store the string. |
|---|
| | 183 | * @param cchBuf The size of the buffer. |
|---|
| | 184 | */ |
|---|
| | 185 | static DECLCALLBACK(int) dbgfR3MemReadString(PVM pVM, PCDBGFADDRESS pAddress, char *pszBuf, size_t cchBuf) |
|---|
| | 186 | { |
|---|
| | 187 | /* |
|---|
| | 188 | * Validate the input we use, PGM does the rest. |
|---|
| | 189 | */ |
|---|
| | 190 | if (!DBGFR3AddrIsValid(pVM, pAddress)) |
|---|
| | 191 | return VERR_INVALID_POINTER; |
|---|
| | 192 | if (!VALID_PTR(pszBuf)) |
|---|
| | 193 | return VERR_INVALID_POINTER; |
|---|
| | 194 | if (DBGFADDRESS_IS_HMA(pAddress)) |
|---|
| | 195 | return VERR_INVALID_POINTER; |
|---|
| | 196 | |
|---|
| | 197 | /* |
|---|
| | 198 | * Select DBGF worker by addressing mode. |
|---|
| | 199 | */ |
|---|
| | 200 | int rc; |
|---|
| | 201 | PGMMODE enmMode = PGMGetGuestMode(pVM); |
|---|
| | 202 | if ( enmMode == PGMMODE_REAL |
|---|
| | 203 | || enmMode == PGMMODE_PROTECTED |
|---|
| | 204 | || DBGFADDRESS_IS_PHYS(pAddress) ) |
|---|
| | 205 | rc = PGMPhysReadGCPhys(pVM, pszBuf, pAddress->FlatPtr, cchBuf); |
|---|
| | 206 | else |
|---|
| | 207 | rc = PGMPhysReadGCPtr(pVM, pszBuf, pAddress->FlatPtr, cchBuf); |
|---|
| | 208 | |
|---|
| | 209 | /* |
|---|
| | 210 | * Make sure the result is terminated and that overflow is signaled. |
|---|
| | 211 | */ |
|---|
| | 212 | if (!memchr(pszBuf, '\0', cchBuf)) |
|---|
| | 213 | { |
|---|
| | 214 | pszBuf[cchBuf - 1] = '\0'; |
|---|
| | 215 | rc = VINF_BUFFER_OVERFLOW; |
|---|
| | 216 | } |
|---|
| | 217 | /* |
|---|
| | 218 | * Handle partial reads (not perfect). |
|---|
| | 219 | */ |
|---|
| | 220 | else if (RT_FAILURE(rc)) |
|---|
| | 221 | { |
|---|
| | 222 | if (pszBuf[0]) |
|---|
| | 223 | rc = VINF_SUCCESS; |
|---|
| | 224 | } |
|---|
| | 225 | |
|---|
| | 226 | return rc; |
|---|
| | 227 | } |
|---|
| | 228 | |
|---|
| | 229 | |
|---|
| | 230 | /** |
|---|
| | 231 | * Read a zero terminated string from guest memory. |
|---|
| | 232 | * |
|---|
| | 233 | * @returns VBox status code. |
|---|
| | 234 | * @param pVM Pointer to the shared VM structure. |
|---|
| | 235 | * @param pAddress Where to start reading. |
|---|
| | 236 | * @param pszBuf Where to store the string. |
|---|
| | 237 | * @param cchBuf The size of the buffer. |
|---|
| | 238 | */ |
|---|
| | 239 | DBGFR3DECL(int) DBGFR3MemReadString(PVM pVM, PCDBGFADDRESS pAddress, char *pszBuf, size_t cchBuf) |
|---|
| | 240 | { |
|---|
| | 241 | /* |
|---|
| | 242 | * Validate and zero output. |
|---|
| | 243 | */ |
|---|
| | 244 | if (!VALID_PTR(pszBuf)) |
|---|
| | 245 | return VERR_INVALID_POINTER; |
|---|
| | 246 | if (cchBuf <= 0) |
|---|
| | 247 | return VERR_INVALID_PARAMETER; |
|---|
| | 248 | memset(pszBuf, 0, cchBuf); |
|---|
| | 249 | |
|---|
| | 250 | /* |
|---|
| | 251 | * Pass it on to the EMT. |
|---|
| | 252 | */ |
|---|
| | 253 | PVMREQ pReq; |
|---|
| | 254 | int rc = VMR3ReqCallU(pVM->pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)dbgfR3MemReadString, 4, |
|---|
| | 255 | pVM, pAddress, pszBuf, cchBuf); |
|---|
| | 256 | if (VBOX_SUCCESS(rc)) |
|---|
| | 257 | rc = pReq->iStatus; |
|---|
| | 258 | VMR3ReqFree(pReq); |
|---|
| | 259 | |
|---|
| | 260 | return rc; |
|---|
| | 261 | } |
|---|
| | 262 | |
|---|