VirtualBox

source: vbox/trunk/src/VBox/VMM/DBGFDisas.cpp@ 28800

Last change on this file since 28800 was 28800, checked in by vboxsync, 14 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 23.5 KB
Line 
1/* $Id: DBGFDisas.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, Disassembler.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
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
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_DBGF
22#include <VBox/dbgf.h>
23#include <VBox/selm.h>
24#include <VBox/mm.h>
25#include <VBox/pgm.h>
26#include <VBox/cpum.h>
27#include "DBGFInternal.h"
28#include <VBox/dis.h>
29#include <VBox/err.h>
30#include <VBox/param.h>
31#include <VBox/vm.h>
32
33#include <VBox/log.h>
34#include <iprt/assert.h>
35#include <iprt/string.h>
36#include <iprt/alloca.h>
37#include <iprt/ctype.h>
38
39
40/*******************************************************************************
41* Structures and Typedefs *
42*******************************************************************************/
43/**
44 * Structure used when disassembling and instructions in DBGF.
45 * This is used so the reader function can get the stuff it needs.
46 */
47typedef struct
48{
49 /** The core structure. */
50 DISCPUSTATE Cpu;
51 /** The VM handle. */
52 PVM pVM;
53 /** The VMCPU handle. */
54 PVMCPU pVCpu;
55 /** The address space for resolving symbol. */
56 RTDBGAS hAs;
57 /** Pointer to the first byte in the segemnt. */
58 RTGCUINTPTR GCPtrSegBase;
59 /** Pointer to the byte after the end of the segment. (might have wrapped!) */
60 RTGCUINTPTR GCPtrSegEnd;
61 /** The size of the segment minus 1. */
62 RTGCUINTPTR cbSegLimit;
63 /** The guest paging mode. */
64 PGMMODE enmMode;
65 /** Pointer to the current page - R3 Ptr. */
66 void const *pvPageR3;
67 /** Pointer to the current page - GC Ptr. */
68 RTGCPTR pvPageGC;
69 /** Pointer to the next instruction (relative to GCPtrSegBase). */
70 RTGCUINTPTR GCPtrNext;
71 /** The lock information that PGMPhysReleasePageMappingLock needs. */
72 PGMPAGEMAPLOCK PageMapLock;
73 /** Whether the PageMapLock is valid or not. */
74 bool fLocked;
75 /** 64 bits mode or not. */
76 bool f64Bits;
77} DBGFDISASSTATE, *PDBGFDISASSTATE;
78
79
80/*******************************************************************************
81* Internal Functions *
82*******************************************************************************/
83static DECLCALLBACK(int) dbgfR3DisasInstrRead(RTUINTPTR pSrc, uint8_t *pDest, uint32_t size, void *pvUserdata);
84
85
86
87/**
88 * Calls the dissassembler with the proper reader functions and such for disa
89 *
90 * @returns VBox status code.
91 * @param pVM VM handle
92 * @param pVCpu VMCPU handle
93 * @param pSelInfo The selector info.
94 * @param enmMode The guest paging mode.
95 * @param GCPtr The GC pointer (selector offset).
96 * @param pState The disas CPU state.
97 */
98static int dbgfR3DisasInstrFirst(PVM pVM, PVMCPU pVCpu, PDBGFSELINFO pSelInfo, PGMMODE enmMode, RTGCPTR GCPtr, PDBGFDISASSTATE pState)
99{
100 pState->GCPtrSegBase = pSelInfo->GCPtrBase;
101 pState->GCPtrSegEnd = pSelInfo->cbLimit + 1 + (RTGCUINTPTR)pSelInfo->GCPtrBase;
102 pState->cbSegLimit = pSelInfo->cbLimit;
103 pState->enmMode = enmMode;
104 pState->pvPageGC = 0;
105 pState->pvPageR3 = NULL;
106 pState->hAs = pSelInfo->fFlags & DBGFSELINFO_FLAGS_HYPER /** @todo Deal more explicitly with RC in DBGFR3Disas*. */
107 ? DBGF_AS_RC_AND_GC_GLOBAL
108 : DBGF_AS_GLOBAL;
109 pState->pVM = pVM;
110 pState->pVCpu = pVCpu;
111 pState->fLocked = false;
112 pState->f64Bits = enmMode >= PGMMODE_AMD64 && pSelInfo->u.Raw.Gen.u1Long;
113 uint32_t cbInstr;
114 int rc = DISCoreOneEx(GCPtr,
115 pState->f64Bits
116 ? CPUMODE_64BIT
117 : pSelInfo->u.Raw.Gen.u1DefBig
118 ? CPUMODE_32BIT
119 : CPUMODE_16BIT,
120 dbgfR3DisasInstrRead,
121 &pState->Cpu,
122 &pState->Cpu,
123 &cbInstr);
124 if (RT_SUCCESS(rc))
125 {
126 pState->GCPtrNext = GCPtr + cbInstr;
127 return VINF_SUCCESS;
128 }
129
130 /* cleanup */
131 if (pState->fLocked)
132 {
133 PGMPhysReleasePageMappingLock(pVM, &pState->PageMapLock);
134 pState->fLocked = false;
135 }
136 return rc;
137}
138
139
140#if 0
141/**
142 * Calls the dissassembler for disassembling the next instruction.
143 *
144 * @returns VBox status code.
145 * @param pState The disas CPU state.
146 */
147static int dbgfR3DisasInstrNext(PDBGFDISASSTATE pState)
148{
149 uint32_t cbInstr;
150 int rc = DISInstr(&pState->Cpu, (void *)pState->GCPtrNext, 0, &cbInstr, NULL);
151 if (RT_SUCCESS(rc))
152 {
153 pState->GCPtrNext = GCPtr + cbInstr;
154 return VINF_SUCCESS;
155 }
156 return rc;
157}
158#endif
159
160
161/**
162 * Done with the dissassembler state, free associated resources.
163 *
164 * @param pState The disas CPU state ++.
165 */
166static void dbgfR3DisasInstrDone(PDBGFDISASSTATE pState)
167{
168 if (pState->fLocked)
169 {
170 PGMPhysReleasePageMappingLock(pState->pVM, &pState->PageMapLock);
171 pState->fLocked = false;
172 }
173}
174
175
176/**
177 * Instruction reader.
178 *
179 * @returns VBox status code. (Why this is a int32_t and not just an int is also beyond me.)
180 * @param PtrSrc Address to read from.
181 * In our case this is relative to the selector pointed to by the 2nd user argument of uDisCpu.
182 * @param pu8Dst Where to store the bytes.
183 * @param cbRead Number of bytes to read.
184 * @param uDisCpu Pointer to the disassembler cpu state. (Why this is a VBOXHUINTPTR is beyond me...)
185 * In this context it's always pointer to the Core of a DBGFDISASSTATE.
186 */
187static DECLCALLBACK(int) dbgfR3DisasInstrRead(RTUINTPTR PtrSrc, uint8_t *pu8Dst, uint32_t cbRead, void *pvDisCpu)
188{
189 PDBGFDISASSTATE pState = (PDBGFDISASSTATE)pvDisCpu;
190 Assert(cbRead > 0);
191 for (;;)
192 {
193 RTGCUINTPTR GCPtr = PtrSrc + pState->GCPtrSegBase;
194
195 /* Need to update the page translation? */
196 if ( !pState->pvPageR3
197 || (GCPtr >> PAGE_SHIFT) != (pState->pvPageGC >> PAGE_SHIFT))
198 {
199 int rc = VINF_SUCCESS;
200
201 /* translate the address */
202 pState->pvPageGC = GCPtr & PAGE_BASE_GC_MASK;
203 if (MMHyperIsInsideArea(pState->pVM, pState->pvPageGC))
204 {
205 pState->pvPageR3 = MMHyperRCToR3(pState->pVM, (RTRCPTR)pState->pvPageGC);
206 if (!pState->pvPageR3)
207 rc = VERR_INVALID_POINTER;
208 }
209 else
210 {
211 if (pState->fLocked)
212 PGMPhysReleasePageMappingLock(pState->pVM, &pState->PageMapLock);
213
214 if (pState->enmMode <= PGMMODE_PROTECTED)
215 rc = PGMPhysGCPhys2CCPtrReadOnly(pState->pVM, pState->pvPageGC, &pState->pvPageR3, &pState->PageMapLock);
216 else
217 rc = PGMPhysGCPtr2CCPtrReadOnly(pState->pVCpu, pState->pvPageGC, &pState->pvPageR3, &pState->PageMapLock);
218 pState->fLocked = RT_SUCCESS_NP(rc);
219 }
220 if (RT_FAILURE(rc))
221 {
222 pState->pvPageR3 = NULL;
223 return rc;
224 }
225 }
226
227 /* check the segemnt limit */
228 if (!pState->f64Bits && PtrSrc > pState->cbSegLimit)
229 return VERR_OUT_OF_SELECTOR_BOUNDS;
230
231 /* calc how much we can read */
232 uint32_t cb = PAGE_SIZE - (GCPtr & PAGE_OFFSET_MASK);
233 if (!pState->f64Bits)
234 {
235 RTGCUINTPTR cbSeg = pState->GCPtrSegEnd - GCPtr;
236 if (cb > cbSeg && cbSeg)
237 cb = cbSeg;
238 }
239 if (cb > cbRead)
240 cb = cbRead;
241
242 /* read and advance */
243 memcpy(pu8Dst, (char *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb);
244 cbRead -= cb;
245 if (!cbRead)
246 return VINF_SUCCESS;
247 pu8Dst += cb;
248 PtrSrc += cb;
249 }
250}
251
252
253/**
254 * @copydoc FNDISGETSYMBOL
255 */
256static DECLCALLBACK(int) dbgfR3DisasGetSymbol(PCDISCPUSTATE pCpu, uint32_t u32Sel, RTUINTPTR uAddress, char *pszBuf, size_t cchBuf, RTINTPTR *poff, void *pvUser)
257{
258 PDBGFDISASSTATE pState = (PDBGFDISASSTATE)pCpu;
259 PCDBGFSELINFO pSelInfo = (PCDBGFSELINFO)pvUser;
260 DBGFADDRESS Addr;
261 RTDBGSYMBOL Sym;
262 RTGCINTPTR off;
263 int rc;
264
265 if ( DIS_FMT_SEL_IS_REG(u32Sel)
266 ? DIS_FMT_SEL_GET_REG(u32Sel) == DIS_SELREG_CS
267 : pSelInfo->Sel == DIS_FMT_SEL_GET_VALUE(u32Sel))
268 {
269 rc = DBGFR3AddrFromSelInfoOff(pState->pVM, &Addr, pSelInfo, uAddress);
270 if (RT_SUCCESS(rc))
271 rc = DBGFR3AsSymbolByAddr(pState->pVM, pState->hAs, &Addr, &off, &Sym, NULL /*phMod*/);
272 }
273 else
274 rc = VERR_SYMBOL_NOT_FOUND; /** @todo implement this */
275 if (RT_SUCCESS(rc))
276 {
277 size_t cchName = strlen(Sym.szName);
278 if (cchName >= cchBuf)
279 cchName = cchBuf - 1;
280 memcpy(pszBuf, Sym.szName, cchName);
281 pszBuf[cchName] = '\0';
282
283 *poff = off;
284 }
285
286 return rc;
287}
288
289
290/**
291 * Disassembles the one instruction according to the specified flags and
292 * address, internal worker executing on the EMT of the specified virtual CPU.
293 *
294 * @returns VBox status code.
295 * @param pVM The VM handle.
296 * @param pVCpu The virtual CPU handle.
297 * @param Sel The code selector. This used to determin the 32/16 bit ness and
298 * calculation of the actual instruction address.
299 * @param pGCPtr Pointer to the variable holding the code address
300 * relative to the base of Sel.
301 * @param fFlags Flags controlling where to start and how to format.
302 * A combination of the DBGF_DISAS_FLAGS_* \#defines.
303 * @param pszOutput Output buffer.
304 * @param cchOutput Size of the output buffer.
305 * @param pcbInstr Where to return the size of the instruction.
306 */
307static DECLCALLBACK(int)
308dbgfR3DisasInstrExOnVCpu(PVM pVM, PVMCPU pVCpu, RTSEL Sel, PRTGCPTR pGCPtr, unsigned fFlags,
309 char *pszOutput, uint32_t cchOutput, uint32_t *pcbInstr)
310{
311 VMCPU_ASSERT_EMT(pVCpu);
312 RTGCPTR GCPtr = *pGCPtr;
313
314 /*
315 * Get the Sel and GCPtr if fFlags requests that.
316 */
317 PCCPUMCTXCORE pCtxCore = NULL;
318 CPUMSELREGHID *pHiddenSel = NULL;
319 int rc;
320 if (fFlags & (DBGF_DISAS_FLAGS_CURRENT_GUEST | DBGF_DISAS_FLAGS_CURRENT_HYPER))
321 {
322 if (fFlags & DBGF_DISAS_FLAGS_CURRENT_GUEST)
323 pCtxCore = CPUMGetGuestCtxCore(pVCpu);
324 else
325 pCtxCore = CPUMGetHyperCtxCore(pVCpu);
326 Sel = pCtxCore->cs;
327 pHiddenSel = (CPUMSELREGHID *)&pCtxCore->csHid;
328 GCPtr = pCtxCore->rip;
329 }
330
331 /*
332 * Read the selector info - assume no stale selectors and nasty stuff like that.
333 * Since the selector flags in the CPUMCTX structures aren't up to date unless
334 * we recently visited REM, we'll not search for the selector there.
335 */
336 DBGFSELINFO SelInfo;
337 const PGMMODE enmMode = PGMGetGuestMode(pVCpu);
338 bool fRealModeAddress = false;
339
340 if ( pHiddenSel
341 && CPUMAreHiddenSelRegsValid(pVM))
342 {
343 SelInfo.Sel = Sel;
344 SelInfo.SelGate = 0;
345 SelInfo.GCPtrBase = pHiddenSel->u64Base;
346 SelInfo.cbLimit = pHiddenSel->u32Limit;
347 SelInfo.fFlags = PGMMODE_IS_LONG_MODE(enmMode)
348 ? DBGFSELINFO_FLAGS_LONG_MODE
349 : enmMode != PGMMODE_REAL && (!pCtxCore || !pCtxCore->eflags.Bits.u1VM)
350 ? DBGFSELINFO_FLAGS_PROT_MODE
351 : DBGFSELINFO_FLAGS_REAL_MODE;
352
353 SelInfo.u.Raw.au32[0] = 0;
354 SelInfo.u.Raw.au32[1] = 0;
355 SelInfo.u.Raw.Gen.u16LimitLow = 0xffff;
356 SelInfo.u.Raw.Gen.u4LimitHigh = 0xf;
357 SelInfo.u.Raw.Gen.u1Present = pHiddenSel->Attr.n.u1Present;
358 SelInfo.u.Raw.Gen.u1Granularity = pHiddenSel->Attr.n.u1Granularity;;
359 SelInfo.u.Raw.Gen.u1DefBig = pHiddenSel->Attr.n.u1DefBig;
360 SelInfo.u.Raw.Gen.u1Long = pHiddenSel->Attr.n.u1Long;
361 SelInfo.u.Raw.Gen.u1DescType = pHiddenSel->Attr.n.u1DescType;
362 SelInfo.u.Raw.Gen.u4Type = pHiddenSel->Attr.n.u4Type;
363 fRealModeAddress = !!(SelInfo.fFlags & DBGFSELINFO_FLAGS_REAL_MODE);
364 }
365 else if (Sel == DBGF_SEL_FLAT)
366 {
367 SelInfo.Sel = Sel;
368 SelInfo.SelGate = 0;
369 SelInfo.GCPtrBase = 0;
370 SelInfo.cbLimit = ~0;
371 SelInfo.fFlags = PGMMODE_IS_LONG_MODE(enmMode)
372 ? DBGFSELINFO_FLAGS_LONG_MODE
373 : enmMode != PGMMODE_REAL
374 ? DBGFSELINFO_FLAGS_PROT_MODE
375 : DBGFSELINFO_FLAGS_REAL_MODE;
376 SelInfo.u.Raw.au32[0] = 0;
377 SelInfo.u.Raw.au32[1] = 0;
378 SelInfo.u.Raw.Gen.u16LimitLow = 0xffff;
379 SelInfo.u.Raw.Gen.u4LimitHigh = 0xf;
380
381 if (CPUMAreHiddenSelRegsValid(pVM))
382 { /* Assume the current CS defines the execution mode. */
383 pCtxCore = CPUMGetGuestCtxCore(pVCpu);
384 pHiddenSel = (CPUMSELREGHID *)&pCtxCore->csHid;
385
386 SelInfo.u.Raw.Gen.u1Present = pHiddenSel->Attr.n.u1Present;
387 SelInfo.u.Raw.Gen.u1Granularity = pHiddenSel->Attr.n.u1Granularity;;
388 SelInfo.u.Raw.Gen.u1DefBig = pHiddenSel->Attr.n.u1DefBig;
389 SelInfo.u.Raw.Gen.u1Long = pHiddenSel->Attr.n.u1Long;
390 SelInfo.u.Raw.Gen.u1DescType = pHiddenSel->Attr.n.u1DescType;
391 SelInfo.u.Raw.Gen.u4Type = pHiddenSel->Attr.n.u4Type;
392 }
393 else
394 {
395 SelInfo.u.Raw.Gen.u1Present = 1;
396 SelInfo.u.Raw.Gen.u1Granularity = 1;
397 SelInfo.u.Raw.Gen.u1DefBig = 1;
398 SelInfo.u.Raw.Gen.u1DescType = 1;
399 SelInfo.u.Raw.Gen.u4Type = X86_SEL_TYPE_EO;
400 }
401 }
402 else if ( !(fFlags & DBGF_DISAS_FLAGS_CURRENT_HYPER)
403 && ( (pCtxCore && pCtxCore->eflags.Bits.u1VM)
404 || enmMode == PGMMODE_REAL) )
405 { /* V86 mode or real mode - real mode addressing */
406 SelInfo.Sel = Sel;
407 SelInfo.SelGate = 0;
408 SelInfo.GCPtrBase = Sel * 16;
409 SelInfo.cbLimit = ~0;
410 SelInfo.fFlags = DBGFSELINFO_FLAGS_REAL_MODE;
411 SelInfo.u.Raw.au32[0] = 0;
412 SelInfo.u.Raw.au32[1] = 0;
413 SelInfo.u.Raw.Gen.u16LimitLow = 0xffff;
414 SelInfo.u.Raw.Gen.u4LimitHigh = 0xf;
415 SelInfo.u.Raw.Gen.u1Present = 1;
416 SelInfo.u.Raw.Gen.u1Granularity = 1;
417 SelInfo.u.Raw.Gen.u1DefBig = 0; /* 16 bits */
418 SelInfo.u.Raw.Gen.u1DescType = 1;
419 SelInfo.u.Raw.Gen.u4Type = X86_SEL_TYPE_EO;
420 fRealModeAddress = true;
421 }
422 else
423 {
424 rc = SELMR3GetSelectorInfo(pVM, pVCpu, Sel, &SelInfo);
425 if (RT_FAILURE(rc))
426 {
427 RTStrPrintf(pszOutput, cchOutput, "Sel=%04x -> %Rrc\n", Sel, rc);
428 return rc;
429 }
430 }
431
432 /*
433 * Disassemble it.
434 */
435 DBGFDISASSTATE State;
436 rc = dbgfR3DisasInstrFirst(pVM, pVCpu, &SelInfo, enmMode, GCPtr, &State);
437 if (RT_FAILURE(rc))
438 {
439 RTStrPrintf(pszOutput, cchOutput, "Disas -> %Rrc\n", rc);
440 return rc;
441 }
442
443 /*
444 * Format it.
445 */
446 char szBuf[512];
447 DISFormatYasmEx(&State.Cpu, szBuf, sizeof(szBuf),
448 DIS_FMT_FLAGS_RELATIVE_BRANCH,
449 fFlags & DBGF_DISAS_FLAGS_NO_SYMBOLS ? NULL : dbgfR3DisasGetSymbol,
450 &SelInfo);
451
452 /*
453 * Print it to the user specified buffer.
454 */
455 if (fFlags & DBGF_DISAS_FLAGS_NO_BYTES)
456 {
457 if (fFlags & DBGF_DISAS_FLAGS_NO_ADDRESS)
458 RTStrPrintf(pszOutput, cchOutput, "%s", szBuf);
459 else if (fRealModeAddress)
460 RTStrPrintf(pszOutput, cchOutput, "%04x:%04x %s", Sel, (unsigned)GCPtr, szBuf);
461 else if (Sel == DBGF_SEL_FLAT)
462 {
463 if (enmMode >= PGMMODE_AMD64)
464 RTStrPrintf(pszOutput, cchOutput, "%RGv %s", GCPtr, szBuf);
465 else
466 RTStrPrintf(pszOutput, cchOutput, "%08RX32 %s", (uint32_t)GCPtr, szBuf);
467 }
468 else
469 {
470 if (enmMode >= PGMMODE_AMD64)
471 RTStrPrintf(pszOutput, cchOutput, "%04x:%RGv %s", Sel, GCPtr, szBuf);
472 else
473 RTStrPrintf(pszOutput, cchOutput, "%04x:%08RX32 %s", Sel, (uint32_t)GCPtr, szBuf);
474 }
475 }
476 else
477 {
478 uint32_t cbBits = State.Cpu.opsize;
479 uint8_t *pau8Bits = (uint8_t *)alloca(cbBits);
480 rc = dbgfR3DisasInstrRead(GCPtr, pau8Bits, cbBits, &State);
481 AssertRC(rc);
482 if (fFlags & DBGF_DISAS_FLAGS_NO_ADDRESS)
483 RTStrPrintf(pszOutput, cchOutput, "%.*Rhxs%*s %s",
484 cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
485 szBuf);
486 else if (fRealModeAddress)
487 RTStrPrintf(pszOutput, cchOutput, "%04x:%04x %.*Rhxs%*s %s",
488 Sel, (unsigned)GCPtr,
489 cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
490 szBuf);
491 else if (Sel == DBGF_SEL_FLAT)
492 {
493 if (enmMode >= PGMMODE_AMD64)
494 RTStrPrintf(pszOutput, cchOutput, "%RGv %.*Rhxs%*s %s",
495 GCPtr,
496 cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
497 szBuf);
498 else
499 RTStrPrintf(pszOutput, cchOutput, "%08RX32 %.*Rhxs%*s %s",
500 (uint32_t)GCPtr,
501 cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
502 szBuf);
503 }
504 else
505 {
506 if (enmMode >= PGMMODE_AMD64)
507 RTStrPrintf(pszOutput, cchOutput, "%04x:%RGv %.*Rhxs%*s %s",
508 Sel, GCPtr,
509 cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
510 szBuf);
511 else
512 RTStrPrintf(pszOutput, cchOutput, "%04x:%08RX32 %.*Rhxs%*s %s",
513 Sel, (uint32_t)GCPtr,
514 cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
515 szBuf);
516 }
517 }
518
519 if (pcbInstr)
520 *pcbInstr = State.Cpu.opsize;
521
522 dbgfR3DisasInstrDone(&State);
523 return VINF_SUCCESS;
524}
525
526
527/**
528 * Disassembles the one instruction according to the specified flags and address.
529 *
530 * @returns VBox status code.
531 * @param pVM VM handle.
532 * @param idCpu The ID of virtual CPU.
533 * @param Sel The code selector. This used to determin the 32/16 bit ness and
534 * calculation of the actual instruction address.
535 * @param GCPtr The code address relative to the base of Sel.
536 * @param fFlags Flags controlling where to start and how to format.
537 * A combination of the DBGF_DISAS_FLAGS_* \#defines.
538 * @param pszOutput Output buffer.
539 * @param cchOutput Size of the output buffer.
540 * @param pcbInstr Where to return the size of the instruction.
541 *
542 * @remarks May have to switch to the EMT of the virtual CPU in order to do
543 * address conversion.
544 */
545VMMR3DECL(int) DBGFR3DisasInstrEx(PVM pVM, VMCPUID idCpu, RTSEL Sel, RTGCPTR GCPtr, unsigned fFlags,
546 char *pszOutput, uint32_t cchOutput, uint32_t *pcbInstr)
547{
548 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
549 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
550
551 /*
552 * Optimize the common case where we're called on the EMT of idCpu since
553 * we're using this all the time when logging.
554 */
555 int rc;
556 PVMCPU pVCpu = VMMGetCpu(pVM);
557 if ( pVCpu
558 && pVCpu->idCpu == idCpu)
559 rc = dbgfR3DisasInstrExOnVCpu(pVM, pVCpu, Sel, &GCPtr, fFlags, pszOutput, cchOutput, pcbInstr);
560 else
561 rc = VMR3ReqCallWait(pVM, idCpu, (PFNRT)dbgfR3DisasInstrExOnVCpu, 8,
562 pVM, VMMGetCpuById(pVM, idCpu), Sel, &GCPtr, fFlags, pszOutput, cchOutput, pcbInstr);
563 return rc;
564}
565
566
567/**
568 * Disassembles the current guest context instruction.
569 * All registers and data will be displayed. Addresses will be attempted resolved to symbols.
570 *
571 * @returns VBox status code.
572 * @param pVCpu VMCPU handle.
573 * @param pszOutput Output buffer.
574 * @param cchOutput Size of the output buffer.
575 */
576VMMR3DECL(int) DBGFR3DisasInstrCurrent(PVMCPU pVCpu, char *pszOutput, uint32_t cchOutput)
577{
578 *pszOutput = '\0';
579 AssertReturn(pVCpu, VERR_INVALID_CONTEXT);
580 return DBGFR3DisasInstrEx(pVCpu->pVMR3, pVCpu->idCpu, 0, 0, DBGF_DISAS_FLAGS_CURRENT_GUEST,
581 pszOutput, cchOutput, NULL);
582}
583
584
585/**
586 * Disassembles the current guest context instruction and writes it to the log.
587 * All registers and data will be displayed. Addresses will be attempted resolved to symbols.
588 *
589 * @returns VBox status code.
590 * @param pVCpu VMCPU handle.
591 * @param pszPrefix Short prefix string to the dissassembly string. (optional)
592 */
593VMMR3DECL(int) DBGFR3DisasInstrCurrentLogInternal(PVMCPU pVCpu, const char *pszPrefix)
594{
595 char szBuf[256];
596 szBuf[0] = '\0';
597 int rc = DBGFR3DisasInstrCurrent(pVCpu, &szBuf[0], sizeof(szBuf));
598 if (RT_FAILURE(rc))
599 RTStrPrintf(szBuf, sizeof(szBuf), "DBGFR3DisasInstrCurrentLog failed with rc=%Rrc\n", rc);
600 if (pszPrefix && *pszPrefix)
601 RTLogPrintf("%s-CPU%d: %s\n", pszPrefix, pVCpu->idCpu, szBuf);
602 else
603 RTLogPrintf("%s\n", szBuf);
604 return rc;
605}
606
607
608
609/**
610 * Disassembles the specified guest context instruction and writes it to the log.
611 * Addresses will be attempted resolved to symbols.
612 *
613 * @returns VBox status code.
614 * @param pVM VM handle.
615 * @param pVCpu The virtual CPU handle, defaults to CPU 0 if NULL.
616 * @param Sel The code selector. This used to determin the 32/16 bit-ness and
617 * calculation of the actual instruction address.
618 * @param GCPtr The code address relative to the base of Sel.
619 */
620VMMR3DECL(int) DBGFR3DisasInstrLogInternal(PVMCPU pVCpu, RTSEL Sel, RTGCPTR GCPtr)
621{
622 char szBuf[256];
623 szBuf[0] = '\0';
624 int rc = DBGFR3DisasInstrEx(pVCpu->pVMR3, pVCpu->idCpu, Sel, GCPtr, 0, &szBuf[0], sizeof(szBuf), NULL);
625 if (RT_FAILURE(rc))
626 RTStrPrintf(szBuf, sizeof(szBuf), "DBGFR3DisasInstrLog(, %RTsel, %RGv) failed with rc=%Rrc\n", Sel, GCPtr, rc);
627 RTLogPrintf("%s\n", szBuf);
628 return rc;
629}
630
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use