VirtualBox

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

Last change on this file since 1995 was 986, checked in by vboxsync, 18 years ago

Fixed confusion between hyper disasm request and real mode. Also we're converting pages, not the read size.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 23.9 KB
Line 
1/* $Id: DBGFDisas.cpp 986 2007-02-19 17:24:30Z vboxsync $ */
2/** @file
3 * VMM DBGF - Debugger Facility, Disassembler.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DBGF
27#include <VBox/dbgf.h>
28#include <VBox/selm.h>
29#include <VBox/mm.h>
30#include <VBox/pgm.h>
31#include "DBGFInternal.h"
32#include <VBox/dis.h>
33#include <VBox/err.h>
34#include <VBox/param.h>
35
36#include <VBox/log.h>
37#include <iprt/assert.h>
38#include <iprt/string.h>
39#include <iprt/alloca.h>
40#include <iprt/ctype.h>
41
42
43/*******************************************************************************
44* Internal Functions *
45*******************************************************************************/
46static DECLCALLBACK(int32_t) dbgfR3DisasInstrRead(RTHCUINTPTR pSrc, uint8_t *pDest, uint32_t size, RTHCUINTPTR dwUserdata);
47
48
49/**
50 * Structure used when disassembling and instructions in DBGF.
51 * This is used so the reader function can get the stuff it needs.
52 */
53typedef struct
54{
55 /** The core structure. */
56 DISCPUSTATE Cpu;
57 /** The VM handle. */
58 PVM pVM;
59 /** Pointer to the first byte in the segemnt. */
60 RTGCUINTPTR GCPtrSegBase;
61 /** Pointer to the byte after the end of the segment. (might have wrapped!) */
62 RTGCUINTPTR GCPtrSegEnd;
63 /** The size of the segment minus 1. */
64 RTGCUINTPTR cbSegLimit;
65 /** The guest paging mode. */
66 PGMMODE enmMode;
67 /** Pointer to the current page - HC Ptr. */
68 void *pvPageHC;
69 /** Pointer to the current page - GC Ptr. */
70 RTGCPTR pvPageGC;
71 /** The rc of the operation.
72 * @todo r=bird: it's rather annoying that we have to keep track of the status code of the operation.
73 * When we've got time we should adjust the disassembler to use VBox status codes and not
74 * boolean returns.
75 */
76 int rc;
77 /** Pointer to the next instruction (relative to GCPtrSegBase). */
78 RTGCUINTPTR GCPtrNext;
79} DBGFDISASSTATE, *PDBGFDISASSTATE;
80
81
82
83/**
84 * Calls the dissassembler with the proper reader functions and such for disa
85 *
86 * @returns VBox status code.
87 * @param pVM VM handle
88 * @param pSelInfo The selector info.
89 * @param enmMode The guest paging mode.
90 * @param GCPtr The GC pointer (selector offset).
91 * @param pState The disas CPU state.
92 */
93static int dbgfR3DisasInstrFirst(PVM pVM, PSELMSELINFO pSelInfo, PGMMODE enmMode, RTGCPTR GCPtr, PDBGFDISASSTATE pState)
94{
95 pState->Cpu.mode = pSelInfo->Raw.Gen.u1DefBig ? CPUMODE_32BIT : CPUMODE_16BIT;
96 pState->Cpu.pfnReadBytes = dbgfR3DisasInstrRead;
97 pState->GCPtrSegBase = pSelInfo->GCPtrBase;
98 pState->GCPtrSegEnd = pSelInfo->cbLimit + 1 + (RTGCUINTPTR)pSelInfo->GCPtrBase;
99 pState->cbSegLimit = pSelInfo->cbLimit;
100 pState->enmMode = enmMode;
101 pState->pvPageGC = 0;
102 pState->pvPageHC = NULL;
103 pState->rc = VINF_SUCCESS;
104 pState->pVM = pVM;
105 Assert((uintptr_t)GCPtr == GCPtr);
106 uint32_t cbInstr;
107 if (DISInstr(&pState->Cpu, GCPtr, 0, &cbInstr, NULL))
108 {
109 pState->GCPtrNext = GCPtr + cbInstr;
110 return VINF_SUCCESS;
111 }
112 if (VBOX_FAILURE(pState->rc))
113 return pState->rc;
114 return VERR_GENERAL_FAILURE;
115}
116
117
118#if 0
119/**
120 * Calls the dissassembler for disassembling the next instruction.
121 *
122 * @returns VBox status code.
123 * @param pState The disas CPU state.
124 */
125static int dbgfR3DisasInstrNext(PDBGFDISASSTATE pState)
126{
127 pState->rc = VINF_SUCCESS;
128 uint32_t cbInstr;
129 if (DISInstr(&pState->Cpu, (void *)pState->GCPtrNext, 0, &cbInstr, NULL))
130 {
131 pState->GCPtrNext = GCPtr + cbInstr;
132 return VINF_SUCCESS;
133 }
134 if (VBOX_FAILURE(pState->rc))
135 return pState->rc;
136 return VERR_GENERAL_FAILURE;
137}
138#endif
139
140
141/**
142 * Instruction reader.
143 *
144 * @returns VBox status code. (Why this is a int32_t and not just an int is also beyond me.)
145 * @param PtrSrc Address to read from.
146 * In our case this is relative to the selector pointed to by the 2nd user argument of uDisCpu.
147 * @param pu8Dst Where to store the bytes.
148 * @param cbRead Number of bytes to read.
149 * @param uDisCpu Pointer to the disassembler cpu state. (Why this is a VBOXHUINTPTR is beyond me...)
150 * In this context it's always pointer to the Core of a DBGFDISASSTATE.
151 */
152static DECLCALLBACK(int32_t) dbgfR3DisasInstrRead(RTHCUINTPTR PtrSrc, uint8_t *pu8Dst, uint32_t cbRead, RTHCUINTPTR uDisCpu)
153{
154 PDBGFDISASSTATE pState = (PDBGFDISASSTATE)uDisCpu;
155 Assert(cbRead > 0);
156 for (;;)
157 {
158 RTGCUINTPTR GCPtr = PtrSrc + pState->GCPtrSegBase;
159
160 /* Need to update the page translation? */
161 if ( !pState->pvPageHC
162 || (GCPtr >> PAGE_SHIFT) != (pState->pvPageGC >> PAGE_SHIFT))
163 {
164 /* translate the address */
165 pState->pvPageGC = GCPtr & PAGE_BASE_GC_MASK;
166 if (MMHyperIsInsideArea(pState->pVM, pState->pvPageGC))
167 {
168 pState->pvPageHC = MMHyperGC2HC(pState->pVM, pState->pvPageGC);
169 if (!pState->pvPageHC)
170 pState->rc = VERR_INVALID_POINTER;
171 }
172 else if (pState->enmMode <= PGMMODE_PROTECTED)
173 pState->rc = PGMPhysGCPhys2HCPtr(pState->pVM, pState->pvPageGC, PAGE_SIZE, &pState->pvPageHC);
174 else
175 pState->rc = PGMPhysGCPtr2HCPtr(pState->pVM, pState->pvPageGC, &pState->pvPageHC);
176 if (VBOX_FAILURE(pState->rc))
177 {
178 pState->pvPageHC = NULL;
179 return pState->rc;
180 }
181 }
182
183 /* check the segemnt limit */
184 if (PtrSrc > pState->cbSegLimit)
185 return pState->rc = VERR_OUT_OF_SELECTOR_BOUNDS;
186
187 /* calc how much we can read */
188 uint32_t cb = PAGE_SIZE - (GCPtr & PAGE_OFFSET_MASK);
189 RTGCUINTPTR cbSeg = pState->GCPtrSegEnd - GCPtr;
190 if (cb > cbSeg && cbSeg)
191 cb = cbSeg;
192 if (cb > cbRead)
193 cb = cbRead;
194
195 /* read and advance */
196 memcpy(pu8Dst, (char *)pState->pvPageHC + (GCPtr & PAGE_OFFSET_MASK), cb);
197 cbRead -= cb;
198 if (!cbRead)
199 return VINF_SUCCESS;
200 pu8Dst += cb;
201 PtrSrc += cb;
202 }
203}
204
205
206/**
207 * Copy a string and return pointer to the terminator char in the copy.
208 */
209inline char *mystrpcpy(char *pszDst, const char *pszSrc)
210{
211 size_t cch = strlen(pszSrc);
212 memcpy(pszDst, pszSrc, cch + 1);
213 return pszDst + cch;
214}
215
216
217/**
218 * Disassembles the one instruction according to the specified flags and address.
219 *
220 * @returns VBox status code.
221 * @param pVM VM handle.
222 * @param Sel The code selector. This used to determin the 32/16 bit ness and
223 * calculation of the actual instruction address.
224 * @param GCPtr The code address relative to the base of Sel.
225 * @param fFlags Flags controlling where to start and how to format.
226 * A combination of the DBGF_DISAS_FLAGS_* \#defines.
227 * @param pszOutput Output buffer.
228 * @param cchOutput Size of the output buffer.
229 * @param pcbInstr Where to return the size of the instruction.
230 */
231DBGFR3DECL(int) DBGFR3DisasInstrEx(PVM pVM, RTSEL Sel, RTGCPTR GCPtr, unsigned fFlags, char *pszOutput, uint32_t cchOutput, uint32_t *pcbInstr)
232{
233 /*
234 * Get the Sel and GCPtr if fFlags requests that.
235 */
236 PCCPUMCTXCORE pCtxCore = NULL;
237 int rc;
238 if (fFlags & (DBGF_DISAS_FLAGS_CURRENT_GUEST | DBGF_DISAS_FLAGS_CURRENT_HYPER))
239 {
240 if (fFlags & DBGF_DISAS_FLAGS_CURRENT_GUEST)
241 pCtxCore = CPUMGetGuestCtxCore(pVM);
242 else
243 pCtxCore = CPUMGetHyperCtxCore(pVM);
244 Sel = pCtxCore->cs;
245 GCPtr = pCtxCore->eip;
246 }
247
248 /*
249 * Read the selector info - assume no stale selectors and nasty stuff like that.
250 * Since the selector flags in the CPUMCTX structures aren't up to date unless
251 * we recently visited REM, we'll not search for the selector there.
252 */
253 SELMSELINFO SelInfo;
254 const PGMMODE enmMode = PGMGetGuestMode(pVM);
255 bool fRealModeAddress = false;
256 if ( !(fFlags & DBGF_DISAS_FLAGS_CURRENT_HYPER)
257 && ( (pCtxCore && pCtxCore->eflags.Bits.u1VM)
258 || enmMode == PGMMODE_REAL) )
259 { /* V86 mode or real mode - real mode addressing */
260 SelInfo.GCPtrBase = Sel * 16;
261 SelInfo.cbLimit = ~0;
262 SelInfo.fHyper = false;
263 SelInfo.fRealMode = true;
264 SelInfo.Raw.au32[0] = 0;
265 SelInfo.Raw.au32[1] = 0;
266 SelInfo.Raw.Gen.u16LimitLow = ~0;
267 SelInfo.Raw.Gen.u4LimitHigh = ~0;
268 SelInfo.Raw.Gen.u1Present = 1;
269 SelInfo.Raw.Gen.u1Granularity = 1;
270 SelInfo.Raw.Gen.u1DefBig = 0; /* 16 bits */
271 SelInfo.Raw.Gen.u1DescType = 1;
272 SelInfo.Raw.Gen.u4Type = X86_SEL_TYPE_EO;
273 fRealModeAddress = true;
274 }
275 else if (Sel == DBGF_SEL_FLAT)
276 {
277 SelInfo.GCPtrBase = 0;
278 SelInfo.cbLimit = ~0;
279 SelInfo.fHyper = false;
280 SelInfo.fRealMode = false;
281 SelInfo.Raw.au32[0] = 0;
282 SelInfo.Raw.au32[1] = 0;
283 SelInfo.Raw.Gen.u16LimitLow = ~0;
284 SelInfo.Raw.Gen.u4LimitHigh = ~0;
285 SelInfo.Raw.Gen.u1Present = 1;
286 SelInfo.Raw.Gen.u1Granularity = 1;
287 SelInfo.Raw.Gen.u1DefBig = 1;
288 SelInfo.Raw.Gen.u1DescType = 1;
289 SelInfo.Raw.Gen.u4Type = X86_SEL_TYPE_EO;
290 }
291 else
292 {
293 rc = SELMR3GetSelectorInfo(pVM, Sel, &SelInfo);
294 if (VBOX_FAILURE(rc))
295 {
296 RTStrPrintf(pszOutput, cchOutput, "Sel=%04x -> %Vrc\n", Sel, rc);
297 return rc;
298 }
299 }
300
301 /*
302 * Disassemble it.
303 */
304 DBGFDISASSTATE State;
305 rc = dbgfR3DisasInstrFirst(pVM, &SelInfo, enmMode, GCPtr, &State);
306 if (VBOX_FAILURE(rc))
307 {
308 RTStrPrintf(pszOutput, cchOutput, "Disas -> %Vrc\n", rc);
309 return rc;
310 }
311
312 /*
313 * Format it.
314 */
315 char szBuf[512];
316 char *psz = &szBuf[0];
317
318 /* prefix */
319 if (State.Cpu.prefix & PREFIX_LOCK)
320 psz = (char *)memcpy(psz, "lock ", sizeof("lock ")) + sizeof("lock ") - 1;
321 if (State.Cpu.prefix & PREFIX_REP)
322 psz = (char *)memcpy(psz, "rep(e) ", sizeof("rep(e) ")) + sizeof("rep(e) ") - 1;
323 else if(State.Cpu.prefix & PREFIX_REPNE)
324 psz = (char *)memcpy(psz, "repne ", sizeof("repne ")) + sizeof("repne ") - 1;
325
326 /* the instruction */
327 const char *pszFormat = State.Cpu.pszOpcode;
328 char ch;
329 while ((ch = *pszFormat) && !isspace(ch) && ch != '%')
330 {
331 *psz++ = ch;
332 pszFormat++;
333 }
334 if (isspace(ch))
335 {
336 do *psz++ = ' ';
337#ifdef DEBUG_bird /* Not sure if Sander want's this because of log size */
338 while (psz - szBuf < 8);
339#else
340 while (0);
341#endif
342 while (isspace(*pszFormat))
343 pszFormat++;
344 }
345
346 if (fFlags & DBGF_DISAS_FLAGS_NO_ANNOTATION)
347 pCtxCore = NULL;
348
349 /** @todo implement annotation and symbol lookup! */
350 int iParam = 1;
351 for (;;)
352 {
353 ch = *pszFormat;
354 if (ch == '%')
355 {
356 ch = pszFormat[1];
357 switch (ch)
358 {
359 /*
360 * Relative jump offset.
361 */
362 case 'J':
363 {
364 AssertMsg(iParam == 1, ("Invalid branch parameter nr %d\n", iParam));
365 int32_t i32Disp;
366 if (State.Cpu.param1.flags & USE_IMMEDIATE8_REL)
367 i32Disp = (int32_t)(int8_t)State.Cpu.param1.parval;
368 else if (State.Cpu.param1.flags & USE_IMMEDIATE16_REL)
369 i32Disp = (int32_t)(int16_t)State.Cpu.param1.parval;
370 else if (State.Cpu.param1.flags & USE_IMMEDIATE32_REL)
371 i32Disp = (int32_t)State.Cpu.param1.parval;
372 else
373 {
374 AssertMsgFailed(("Oops!\n"));
375 return VERR_GENERAL_FAILURE;
376 }
377 RTGCUINTPTR GCPtrTarget = (RTGCUINTPTR)GCPtr + State.Cpu.opsize + i32Disp;
378 switch (State.Cpu.opmode)
379 {
380 case CPUMODE_16BIT: GCPtrTarget &= UINT16_MAX; break;
381 case CPUMODE_32BIT: GCPtrTarget &= UINT32_MAX; break;
382 }
383#ifdef DEBUG_bird /* an experiment. */
384 DBGFSYMBOL Sym;
385 RTGCINTPTR off;
386 int rc = DBGFR3SymbolByAddr(pVM, GCPtrTarget + SelInfo.GCPtrBase, &off, &Sym);
387 if ( VBOX_SUCCESS(rc)
388 && Sym.Value - SelInfo.GCPtrBase <= SelInfo.cbLimit
389 && off < _1M * 16 && off > -_1M * 16)
390 {
391 psz += RTStrPrintf(psz, &szBuf[sizeof(szBuf)] - psz, "%s", Sym.szName);
392 if (off > 0)
393 psz += RTStrPrintf(psz, &szBuf[sizeof(szBuf)] - psz, "+%#x", (int)off);
394 else if (off > 0)
395 psz += RTStrPrintf(psz, &szBuf[sizeof(szBuf)] - psz, "-%#x", -(int)off);
396 switch (State.Cpu.opmode)
397 {
398 case CPUMODE_16BIT:
399 psz += RTStrPrintf(psz, &szBuf[sizeof(szBuf)] - psz,
400 i32Disp >= 0 ? " (%04VGv/+%x)" : " (%04VGv/-%x)",
401 GCPtrTarget, i32Disp >= 0 ? i32Disp : -i32Disp);
402 break;
403 case CPUMODE_32BIT:
404 psz += RTStrPrintf(psz, &szBuf[sizeof(szBuf)] - psz,
405 i32Disp >= 0 ? " (%08VGv/+%x)" : " (%08VGv/-%x)",
406 GCPtrTarget, i32Disp >= 0 ? i32Disp : -i32Disp);
407 break;
408 default:
409 psz += RTStrPrintf(psz, &szBuf[sizeof(szBuf)] - psz,
410 i32Disp >= 0 ? " (%VGv/+%x)" : " (%VGv/-%x)",
411 GCPtrTarget, i32Disp >= 0 ? i32Disp : -i32Disp);
412 break;
413 }
414 }
415 else
416#endif /* DEBUG_bird */
417 {
418 switch (State.Cpu.opmode)
419 {
420 case CPUMODE_16BIT:
421 psz += RTStrPrintf(psz, &szBuf[sizeof(szBuf)] - psz,
422 i32Disp >= 0 ? "%04VGv (+%x)" : "%04VGv (-%x)",
423 GCPtrTarget, i32Disp >= 0 ? i32Disp : -i32Disp);
424 break;
425 case CPUMODE_32BIT:
426 psz += RTStrPrintf(psz, &szBuf[sizeof(szBuf)] - psz,
427 i32Disp >= 0 ? "%08VGv (+%x)" : "%08VGv (-%x)",
428 GCPtrTarget, i32Disp >= 0 ? i32Disp : -i32Disp);
429 break;
430 default:
431 psz += RTStrPrintf(psz, &szBuf[sizeof(szBuf)] - psz,
432 i32Disp >= 0 ? "%VGv (+%x)" : "%VGv (-%x)",
433 GCPtrTarget, i32Disp >= 0 ? i32Disp : -i32Disp);
434 break;
435 }
436 }
437 break;
438 }
439
440 case 'A': //direct address
441 case 'C': //control register
442 case 'D': //debug register
443 case 'E': //ModRM specifies parameter
444 case 'F': //Eflags register
445 case 'G': //ModRM selects general register
446 case 'I': //Immediate data
447 case 'M': //ModRM may only refer to memory
448 case 'O': //No ModRM byte
449 case 'P': //ModRM byte selects MMX register
450 case 'Q': //ModRM byte selects MMX register or memory address
451 case 'R': //ModRM byte may only refer to a general register
452 case 'S': //ModRM byte selects a segment register
453 case 'T': //ModRM byte selects a test register
454 case 'V': //ModRM byte selects an XMM/SSE register
455 case 'W': //ModRM byte selects an XMM/SSE register or a memory address
456 case 'X': //DS:SI
457 case 'Y': //ES:DI
458 switch (iParam)
459 {
460 case 1: psz = mystrpcpy(psz, State.Cpu.param1.szParam); break;
461 case 2: psz = mystrpcpy(psz, State.Cpu.param2.szParam); break;
462 case 3: psz = mystrpcpy(psz, State.Cpu.param3.szParam); break;
463 }
464 pszFormat += 2;
465 break;
466
467 case 'e': //register based on operand size (e.g. %eAX)
468 if (State.Cpu.opmode == CPUMODE_32BIT)
469 *psz++ = 'E';
470 *psz++ = pszFormat[2];
471 *psz++ = pszFormat[3];
472 pszFormat += 4;
473 break;
474
475 default:
476 AssertMsgFailed(("Oops! ch=%c\n", ch));
477 break;
478 }
479
480 /* Skip to the next parameter in the format string. */
481 pszFormat = strchr(pszFormat, ',');
482 if (!pszFormat)
483 break;
484 pszFormat++;
485 *psz++ = ch = ',';
486 iParam++;
487 }
488 else
489 {
490 /* output char, but check for parameter separator first. */
491 if (ch == ',')
492 iParam++;
493 *psz++ = ch;
494 if (!ch)
495 break;
496 pszFormat++;
497 }
498
499#ifdef DEBUG_bird /* Not sure if Sander want's this because of log size */
500 /* space after commas */
501 if (ch == ',')
502 {
503 while (isspace(*pszFormat))
504 pszFormat++;
505 *psz++ = ' ';
506 }
507#endif
508 } /* foreach char in pszFormat */
509 *psz = '\0';
510
511 /*
512 * Print it to the user specified buffer.
513 */
514 if (fFlags & DBGF_DISAS_FLAGS_NO_BYTES)
515 {
516 if (fFlags & DBGF_DISAS_FLAGS_NO_ADDRESS)
517 RTStrPrintf(pszOutput, cchOutput, "%s", szBuf);
518 else if (fRealModeAddress)
519 RTStrPrintf(pszOutput, cchOutput, "%04x:%04x %s", Sel, (unsigned)GCPtr, szBuf);
520 else if (Sel == DBGF_SEL_FLAT)
521 RTStrPrintf(pszOutput, cchOutput, "%VGv %s", GCPtr, szBuf);
522 else
523 RTStrPrintf(pszOutput, cchOutput, "%04x:%VGv %s", Sel, GCPtr, szBuf);
524 }
525 else
526 {
527 size_t cbBits = State.Cpu.opsize;
528 uint8_t *pau8Bits = (uint8_t *)alloca(cbBits);
529 rc = dbgfR3DisasInstrRead(GCPtr, pau8Bits, cbBits, (uintptr_t)&State);
530 AssertRC(rc);
531 if (fFlags & DBGF_DISAS_FLAGS_NO_ADDRESS)
532 RTStrPrintf(pszOutput, cchOutput, "%.*Vhxs%*s %s",
533 cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
534 szBuf);
535 else if (fRealModeAddress)
536 RTStrPrintf(pszOutput, cchOutput, "%04x:%04x %.*Vhxs%*s %s",
537 Sel, (unsigned)GCPtr,
538 cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
539 szBuf);
540 else if (Sel == DBGF_SEL_FLAT)
541 RTStrPrintf(pszOutput, cchOutput, "%VGv %.*Vhxs%*s %s",
542 GCPtr,
543 cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
544 szBuf);
545 else
546 RTStrPrintf(pszOutput, cchOutput, "%04x:%VGv %.*Vhxs%*s %s",
547 Sel, GCPtr,
548 cbBits, pau8Bits, cbBits < 8 ? (8 - cbBits) * 3 : 0, "",
549 szBuf);
550
551 }
552
553 if (pcbInstr)
554 *pcbInstr = State.Cpu.opsize;
555 return VINF_SUCCESS;
556}
557
558
559/**
560 * Disassembles an instruction.
561 * Addresses will be tried resolved to symbols
562 *
563 * @returns VBox status code.
564 * @param pVM VM handle.
565 * @param Sel The code selector. This used to determin the 32/16 bit ness and
566 * calculation of the actual instruction address.
567 * @param GCPtr The code address relative to the base of Sel.
568 * @param pszOutput Output buffer.
569 * @param cchOutput Size of the output buffer.
570 */
571DBGFR3DECL(int) DBGFR3DisasInstr(PVM pVM, RTSEL Sel, RTGCPTR GCPtr, char *pszOutput, uint32_t cchOutput)
572{
573 return DBGFR3DisasInstrEx(pVM, Sel, GCPtr, 0, pszOutput, cchOutput, NULL);
574}
575
576
577/**
578 * Disassembles the current guest context instruction.
579 * All registers and data will be displayed. Addresses will be attempted resolved to symbols.
580 *
581 * @returns VBox status code.
582 * @param pVM VM handle.
583 * @param pszOutput Output buffer.
584 * @param cchOutput Size of the output buffer.
585 */
586DBGFR3DECL(int) DBGFR3DisasInstrCurrent(PVM pVM, char *pszOutput, uint32_t cchOutput)
587{
588 return DBGFR3DisasInstrEx(pVM, 0, 0, DBGF_DISAS_FLAGS_CURRENT_GUEST, pszOutput, cchOutput, NULL);
589}
590
591
592/**
593 * Disassembles the current guest context instruction and writes it to the log.
594 * All registers and data will be displayed. Addresses will be attempted resolved to symbols.
595 *
596 * @returns VBox status code.
597 * @param pVM VM handle.
598 * @param pszPrefix Short prefix string to the dissassembly string. (optional)
599 */
600DBGFR3DECL(int) DBGFR3DisasInstrCurrentLogInternal(PVM pVM, const char *pszPrefix)
601{
602 char szBuf[256];
603 szBuf[0] = '\0';
604 int rc = DBGFR3DisasInstrCurrent(pVM, &szBuf[0], sizeof(szBuf));
605 if (VBOX_FAILURE(rc))
606 RTStrPrintf(szBuf, sizeof(szBuf), "DBGFR3DisasInstrCurrentLog failed with rc=%Vrc\n", rc);
607 if (pszPrefix && *pszPrefix)
608 RTLogPrintf("%s: %s\n", pszPrefix, szBuf);
609 else
610 RTLogPrintf("%s\n", szBuf);
611 return rc;
612}
613
614
615
616/**
617 * Disassembles the specified guest context instruction and writes it to the log.
618 * Addresses will be attempted resolved to symbols.
619 *
620 * @returns VBox status code.
621 * @param pVM VM handle.
622 * @param Sel The code selector. This used to determin the 32/16 bit-ness and
623 * calculation of the actual instruction address.
624 * @param GCPtr The code address relative to the base of Sel.
625 */
626DBGFR3DECL(int) DBGFR3DisasInstrLogInternal(PVM pVM, RTSEL Sel, RTGCPTR GCPtr)
627{
628 char szBuf[256];
629 szBuf[0] = '\0';
630 int rc = DBGFR3DisasInstr(pVM, Sel, GCPtr, &szBuf[0], sizeof(szBuf));
631 if (VBOX_FAILURE(rc))
632 RTStrPrintf(szBuf, sizeof(szBuf), "DBGFR3DisasInstrLog(, %RTsel, %RGv) failed with rc=%Vrc\n", Sel, GCPtr, rc);
633 RTLogPrintf("%s\n", szBuf);
634 return rc;
635}
636
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