VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/DBGF.cpp@ 38399

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

VMM,SUPDrv: Created DBGFTrace.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 31.8 KB
Line 
1/* $Id: DBGF.cpp 37410 2011-06-10 15:11:40Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility.
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/** @page pg_dbgf DBGF - The Debugger Facility
20 *
21 * The purpose of the DBGF is to provide an interface for debuggers to
22 * manipulate the VMM without having to mess up the source code for each of
23 * them. The DBGF is always built in and will always work when a debugger
24 * attaches to the VM. The DBGF provides the basic debugger features, such as
25 * halting execution, handling breakpoints, single step execution, instruction
26 * disassembly, info querying, OS specific diggers, symbol and module
27 * management.
28 *
29 * The interface is working in a manner similar to the win32, linux and os2
30 * debugger interfaces. The interface has an asynchronous nature. This comes
31 * from the fact that the VMM and the Debugger are running in different threads.
32 * They are referred to as the "emulation thread" and the "debugger thread", or
33 * as the "ping thread" and the "pong thread, respectivly. (The last set of
34 * names comes from the use of the Ping-Pong synchronization construct from the
35 * RTSem API.)
36 *
37 * @see grp_dbgf
38 *
39 *
40 * @section sec_dbgf_scenario Usage Scenario
41 *
42 * The debugger starts by attaching to the VM. For practical reasons we limit the
43 * number of concurrently attached debuggers to 1 per VM. The action of
44 * attaching to the VM causes the VM to check and generate debug events.
45 *
46 * The debugger then will wait/poll for debug events and issue commands.
47 *
48 * The waiting and polling is done by the DBGFEventWait() function. It will wait
49 * for the emulation thread to send a ping, thus indicating that there is an
50 * event waiting to be processed.
51 *
52 * An event can be a response to a command issued previously, the hitting of a
53 * breakpoint, or running into a bad/fatal VMM condition. The debugger now has
54 * the ping and must respond to the event at hand - the VMM is waiting. This
55 * usually means that the user of the debugger must do something, but it doesn't
56 * have to. The debugger is free to call any DBGF function (nearly at least)
57 * while processing the event.
58 *
59 * Typically the user will issue a request for the execution to be resumed, so
60 * the debugger calls DBGFResume() and goes back to waiting/polling for events.
61 *
62 * When the user eventually terminates the debugging session or selects another
63 * VM, the debugger detaches from the VM. This means that breakpoints are
64 * disabled and that the emulation thread no longer polls for debugger commands.
65 *
66 */
67
68
69/*******************************************************************************
70* Header Files *
71*******************************************************************************/
72#define LOG_GROUP LOG_GROUP_DBGF
73#include <VBox/vmm/dbgf.h>
74#include <VBox/vmm/selm.h>
75#include <VBox/vmm/rem.h>
76#include <VBox/vmm/em.h>
77#include <VBox/vmm/hwaccm.h>
78#include "DBGFInternal.h"
79#include <VBox/vmm/vm.h>
80#include <VBox/err.h>
81
82#include <VBox/log.h>
83#include <iprt/semaphore.h>
84#include <iprt/thread.h>
85#include <iprt/asm.h>
86#include <iprt/time.h>
87#include <iprt/assert.h>
88#include <iprt/stream.h>
89#include <iprt/env.h>
90
91
92/*******************************************************************************
93* Internal Functions *
94*******************************************************************************/
95static int dbgfR3VMMWait(PVM pVM);
96static int dbgfR3VMMCmd(PVM pVM, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution);
97static DECLCALLBACK(int) dbgfR3Attach(PVM pVM);
98
99
100/**
101 * Sets the VMM Debug Command variable.
102 *
103 * @returns Previous command.
104 * @param pVM VM Handle.
105 * @param enmCmd The command.
106 */
107DECLINLINE(DBGFCMD) dbgfR3SetCmd(PVM pVM, DBGFCMD enmCmd)
108{
109 DBGFCMD rc;
110 if (enmCmd == DBGFCMD_NO_COMMAND)
111 {
112 Log2(("DBGF: Setting command to %d (DBGFCMD_NO_COMMAND)\n", enmCmd));
113 rc = (DBGFCMD)ASMAtomicXchgU32((uint32_t volatile *)(void *)&pVM->dbgf.s.enmVMMCmd, enmCmd);
114 VM_FF_CLEAR(pVM, VM_FF_DBGF);
115 }
116 else
117 {
118 Log2(("DBGF: Setting command to %d\n", enmCmd));
119 AssertMsg(pVM->dbgf.s.enmVMMCmd == DBGFCMD_NO_COMMAND, ("enmCmd=%d enmVMMCmd=%d\n", enmCmd, pVM->dbgf.s.enmVMMCmd));
120 rc = (DBGFCMD)ASMAtomicXchgU32((uint32_t volatile *)(void *)&pVM->dbgf.s.enmVMMCmd, enmCmd);
121 VM_FF_SET(pVM, VM_FF_DBGF);
122 VMR3NotifyGlobalFFU(pVM->pUVM, 0 /* didn't notify REM */);
123 }
124 return rc;
125}
126
127
128/**
129 * Initializes the DBGF.
130 *
131 * @returns VBox status code.
132 * @param pVM VM handle.
133 */
134VMMR3DECL(int) DBGFR3Init(PVM pVM)
135{
136 int rc = dbgfR3InfoInit(pVM);
137 if (RT_SUCCESS(rc))
138 rc = dbgfR3TraceInit(pVM);
139 if (RT_SUCCESS(rc))
140 rc = dbgfR3RegInit(pVM);
141 if (RT_SUCCESS(rc))
142 rc = dbgfR3AsInit(pVM);
143 if (RT_SUCCESS(rc))
144 rc = dbgfR3SymInit(pVM);
145 if (RT_SUCCESS(rc))
146 rc = dbgfR3BpInit(pVM);
147 return rc;
148}
149
150
151/**
152 * Terminates and cleans up resources allocated by the DBGF.
153 *
154 * @returns VBox status code.
155 * @param pVM VM Handle.
156 */
157VMMR3DECL(int) DBGFR3Term(PVM pVM)
158{
159 int rc;
160
161 /*
162 * Send a termination event to any attached debugger.
163 */
164 /* wait to become the speaker (we should already be that). */
165 if ( pVM->dbgf.s.fAttached
166 && RTSemPingShouldWait(&pVM->dbgf.s.PingPong))
167 RTSemPingWait(&pVM->dbgf.s.PingPong, 5000);
168
169 /* now, send the event if we're the speaker. */
170 if ( pVM->dbgf.s.fAttached
171 && RTSemPingIsSpeaker(&pVM->dbgf.s.PingPong))
172 {
173 DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
174 if (enmCmd == DBGFCMD_DETACH_DEBUGGER)
175 /* the debugger beat us to initiating the detaching. */
176 rc = VINF_SUCCESS;
177 else
178 {
179 /* ignore the command (if any). */
180 enmCmd = DBGFCMD_NO_COMMAND;
181 pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_TERMINATING;
182 pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_OTHER;
183 rc = RTSemPing(&pVM->dbgf.s.PingPong);
184 }
185
186 /*
187 * Process commands until we get a detached command.
188 */
189 while (RT_SUCCESS(rc) && enmCmd != DBGFCMD_DETACHED_DEBUGGER)
190 {
191 if (enmCmd != DBGFCMD_NO_COMMAND)
192 {
193 /* process command */
194 bool fResumeExecution;
195 DBGFCMDDATA CmdData = pVM->dbgf.s.VMMCmdData;
196 rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
197 enmCmd = DBGFCMD_NO_COMMAND;
198 }
199 else
200 {
201 /* wait for new command. */
202 rc = RTSemPingWait(&pVM->dbgf.s.PingPong, RT_INDEFINITE_WAIT);
203 if (RT_SUCCESS(rc))
204 enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
205 }
206 }
207 }
208
209 /*
210 * Terminate the other bits.
211 */
212 dbgfR3OSTerm(pVM);
213 dbgfR3AsTerm(pVM);
214 dbgfR3RegTerm(pVM);
215 dbgfR3TraceTerm(pVM);
216 dbgfR3InfoTerm(pVM);
217 return VINF_SUCCESS;
218}
219
220
221/**
222 * Applies relocations to data and code managed by this
223 * component. This function will be called at init and
224 * whenever the VMM need to relocate it self inside the GC.
225 *
226 * @param pVM VM handle.
227 * @param offDelta Relocation delta relative to old location.
228 */
229VMMR3DECL(void) DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta)
230{
231 dbgfR3TraceRelocate(pVM);
232 dbgfR3AsRelocate(pVM, offDelta);
233}
234
235
236/**
237 * Waits a little while for a debuggger to attach.
238 *
239 * @returns True is a debugger have attached.
240 * @param pVM VM handle.
241 * @param enmEvent Event.
242 */
243bool dbgfR3WaitForAttach(PVM pVM, DBGFEVENTTYPE enmEvent)
244{
245 /*
246 * First a message.
247 */
248#ifndef RT_OS_L4
249
250# if !defined(DEBUG) || defined(DEBUG_sandervl) || defined(DEBUG_frank) || defined(IEM_VERIFICATION_MODE)
251 int cWait = 10;
252# else
253 int cWait = HWACCMIsEnabled(pVM)
254 && ( enmEvent == DBGFEVENT_ASSERTION_HYPER
255 || enmEvent == DBGFEVENT_FATAL_ERROR)
256 && !RTEnvExist("VBOX_DBGF_WAIT_FOR_ATTACH")
257 ? 10
258 : 150;
259# endif
260 RTStrmPrintf(g_pStdErr, "DBGF: No debugger attached, waiting %d second%s for one to attach (event=%d)\n",
261 cWait / 10, cWait != 10 ? "s" : "", enmEvent);
262 RTStrmFlush(g_pStdErr);
263 while (cWait > 0)
264 {
265 RTThreadSleep(100);
266 if (pVM->dbgf.s.fAttached)
267 {
268 RTStrmPrintf(g_pStdErr, "Attached!\n");
269 RTStrmFlush(g_pStdErr);
270 return true;
271 }
272
273 /* next */
274 if (!(cWait % 10))
275 {
276 RTStrmPrintf(g_pStdErr, "%d.", cWait / 10);
277 RTStrmFlush(g_pStdErr);
278 }
279 cWait--;
280 }
281#endif
282
283 RTStrmPrintf(g_pStdErr, "Stopping the VM!\n");
284 RTStrmFlush(g_pStdErr);
285 return false;
286}
287
288
289/**
290 * Forced action callback.
291 * The VMM will call this from it's main loop when VM_FF_DBGF is set.
292 *
293 * The function checks and executes pending commands from the debugger.
294 *
295 * @returns VINF_SUCCESS normally.
296 * @returns VERR_DBGF_RAISE_FATAL_ERROR to pretend a fatal error happened.
297 * @param pVM VM Handle.
298 */
299VMMR3DECL(int) DBGFR3VMMForcedAction(PVM pVM)
300{
301 int rc = VINF_SUCCESS;
302
303 if (VM_FF_TESTANDCLEAR(pVM, VM_FF_DBGF))
304 {
305 PVMCPU pVCpu = VMMGetCpu(pVM);
306
307 /*
308 * Commands?
309 */
310 if (pVM->dbgf.s.enmVMMCmd != DBGFCMD_NO_COMMAND)
311 {
312 /** @todo stupid GDT/LDT sync hack. go away! */
313 SELMR3UpdateFromCPUM(pVM, pVCpu);
314
315 /*
316 * Process the command.
317 */
318 bool fResumeExecution;
319 DBGFCMDDATA CmdData = pVM->dbgf.s.VMMCmdData;
320 DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
321 rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
322 if (!fResumeExecution)
323 rc = dbgfR3VMMWait(pVM);
324 }
325 }
326 return rc;
327}
328
329
330/**
331 * Flag whether the event implies that we're stopped in the hypervisor code
332 * and have to block certain operations.
333 *
334 * @param pVM The VM handle.
335 * @param enmEvent The event.
336 */
337static void dbgfR3EventSetStoppedInHyperFlag(PVM pVM, DBGFEVENTTYPE enmEvent)
338{
339 switch (enmEvent)
340 {
341 case DBGFEVENT_STEPPED_HYPER:
342 case DBGFEVENT_ASSERTION_HYPER:
343 case DBGFEVENT_BREAKPOINT_HYPER:
344 pVM->dbgf.s.fStoppedInHyper = true;
345 break;
346 default:
347 pVM->dbgf.s.fStoppedInHyper = false;
348 break;
349 }
350}
351
352
353/**
354 * Try to determine the event context.
355 *
356 * @returns debug event context.
357 * @param pVM The VM handle.
358 */
359static DBGFEVENTCTX dbgfR3FigureEventCtx(PVM pVM)
360{
361 /** @todo SMP support! */
362 PVMCPU pVCpu = &pVM->aCpus[0];
363
364 switch (EMGetState(pVCpu))
365 {
366 case EMSTATE_RAW:
367 case EMSTATE_DEBUG_GUEST_RAW:
368 return DBGFEVENTCTX_RAW;
369
370 case EMSTATE_REM:
371 case EMSTATE_DEBUG_GUEST_REM:
372 return DBGFEVENTCTX_REM;
373
374 case EMSTATE_DEBUG_HYPER:
375 case EMSTATE_GURU_MEDITATION:
376 return DBGFEVENTCTX_HYPER;
377
378 default:
379 return DBGFEVENTCTX_OTHER;
380 }
381}
382
383/**
384 * The common event prologue code.
385 * It will set the 'stopped-in-hyper' flag, make sure someone is attached,
386 * and perhaps process any high priority pending actions (none yet).
387 *
388 * @returns VBox status.
389 * @param pVM The VM handle.
390 * @param enmEvent The event to be sent.
391 */
392static int dbgfR3EventPrologue(PVM pVM, DBGFEVENTTYPE enmEvent)
393{
394 /** @todo SMP */
395 PVMCPU pVCpu = VMMGetCpu(pVM);
396
397 /*
398 * Check if a debugger is attached.
399 */
400 if ( !pVM->dbgf.s.fAttached
401 && !dbgfR3WaitForAttach(pVM, enmEvent))
402 {
403 Log(("DBGFR3VMMEventSrc: enmEvent=%d - debugger not attached\n", enmEvent));
404 return VERR_DBGF_NOT_ATTACHED;
405 }
406
407 /*
408 * Sync back the state from the REM.
409 */
410 dbgfR3EventSetStoppedInHyperFlag(pVM, enmEvent);
411 if (!pVM->dbgf.s.fStoppedInHyper)
412 REMR3StateUpdate(pVM, pVCpu);
413
414 /*
415 * Look thru pending commands and finish those which make sense now.
416 */
417 /** @todo Process/purge pending commands. */
418 //int rc = DBGFR3VMMForcedAction(pVM);
419 return VINF_SUCCESS;
420}
421
422
423/**
424 * Sends the event in the event buffer.
425 *
426 * @returns VBox status code.
427 * @param pVM The VM handle.
428 */
429static int dbgfR3SendEvent(PVM pVM)
430{
431 int rc = RTSemPing(&pVM->dbgf.s.PingPong);
432 if (RT_SUCCESS(rc))
433 rc = dbgfR3VMMWait(pVM);
434
435 pVM->dbgf.s.fStoppedInHyper = false;
436 /** @todo sync VMM -> REM after exitting the debugger. everything may change while in the debugger! */
437 return rc;
438}
439
440
441/**
442 * Send a generic debugger event which takes no data.
443 *
444 * @returns VBox status.
445 * @param pVM The VM handle.
446 * @param enmEvent The event to send.
447 */
448VMMR3DECL(int) DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent)
449{
450 int rc = dbgfR3EventPrologue(pVM, enmEvent);
451 if (RT_FAILURE(rc))
452 return rc;
453
454 /*
455 * Send the event and process the reply communication.
456 */
457 pVM->dbgf.s.DbgEvent.enmType = enmEvent;
458 pVM->dbgf.s.DbgEvent.enmCtx = dbgfR3FigureEventCtx(pVM);
459 return dbgfR3SendEvent(pVM);
460}
461
462
463/**
464 * Send a debugger event which takes the full source file location.
465 *
466 * @returns VBox status.
467 * @param pVM The VM handle.
468 * @param enmEvent The event to send.
469 * @param pszFile Source file.
470 * @param uLine Line number in source file.
471 * @param pszFunction Function name.
472 * @param pszFormat Message which accompanies the event.
473 * @param ... Message arguments.
474 */
475VMMR3DECL(int) DBGFR3EventSrc(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, ...)
476{
477 va_list args;
478 va_start(args, pszFormat);
479 int rc = DBGFR3EventSrcV(pVM, enmEvent, pszFile, uLine, pszFunction, pszFormat, args);
480 va_end(args);
481 return rc;
482}
483
484
485/**
486 * Send a debugger event which takes the full source file location.
487 *
488 * @returns VBox status.
489 * @param pVM The VM handle.
490 * @param enmEvent The event to send.
491 * @param pszFile Source file.
492 * @param uLine Line number in source file.
493 * @param pszFunction Function name.
494 * @param pszFormat Message which accompanies the event.
495 * @param args Message arguments.
496 */
497VMMR3DECL(int) DBGFR3EventSrcV(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, va_list args)
498{
499 int rc = dbgfR3EventPrologue(pVM, enmEvent);
500 if (RT_FAILURE(rc))
501 return rc;
502
503 /*
504 * Format the message.
505 */
506 char *pszMessage = NULL;
507 char szMessage[8192];
508 if (pszFormat && *pszFormat)
509 {
510 pszMessage = &szMessage[0];
511 RTStrPrintfV(szMessage, sizeof(szMessage), pszFormat, args);
512 }
513
514 /*
515 * Send the event and process the reply communication.
516 */
517 pVM->dbgf.s.DbgEvent.enmType = enmEvent;
518 pVM->dbgf.s.DbgEvent.enmCtx = dbgfR3FigureEventCtx(pVM);
519 pVM->dbgf.s.DbgEvent.u.Src.pszFile = pszFile;
520 pVM->dbgf.s.DbgEvent.u.Src.uLine = uLine;
521 pVM->dbgf.s.DbgEvent.u.Src.pszFunction = pszFunction;
522 pVM->dbgf.s.DbgEvent.u.Src.pszMessage = pszMessage;
523 return dbgfR3SendEvent(pVM);
524}
525
526
527/**
528 * Send a debugger event which takes the two assertion messages.
529 *
530 * @returns VBox status.
531 * @param pVM The VM handle.
532 * @param enmEvent The event to send.
533 * @param pszMsg1 First assertion message.
534 * @param pszMsg2 Second assertion message.
535 */
536VMMR3DECL(int) DBGFR3EventAssertion(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszMsg1, const char *pszMsg2)
537{
538 int rc = dbgfR3EventPrologue(pVM, enmEvent);
539 if (RT_FAILURE(rc))
540 return rc;
541
542 /*
543 * Send the event and process the reply communication.
544 */
545 pVM->dbgf.s.DbgEvent.enmType = enmEvent;
546 pVM->dbgf.s.DbgEvent.enmCtx = dbgfR3FigureEventCtx(pVM);
547 pVM->dbgf.s.DbgEvent.u.Assert.pszMsg1 = pszMsg1;
548 pVM->dbgf.s.DbgEvent.u.Assert.pszMsg2 = pszMsg2;
549 return dbgfR3SendEvent(pVM);
550}
551
552
553/**
554 * Breakpoint was hit somewhere.
555 * Figure out which breakpoint it is and notify the debugger.
556 *
557 * @returns VBox status.
558 * @param pVM The VM handle.
559 * @param enmEvent DBGFEVENT_BREAKPOINT_HYPER or DBGFEVENT_BREAKPOINT.
560 */
561VMMR3DECL(int) DBGFR3EventBreakpoint(PVM pVM, DBGFEVENTTYPE enmEvent)
562{
563 int rc = dbgfR3EventPrologue(pVM, enmEvent);
564 if (RT_FAILURE(rc))
565 return rc;
566
567 /*
568 * Send the event and process the reply communication.
569 */
570 /** @todo SMP */
571 PVMCPU pVCpu = VMMGetCpu0(pVM);
572
573 pVM->dbgf.s.DbgEvent.enmType = enmEvent;
574 RTUINT iBp = pVM->dbgf.s.DbgEvent.u.Bp.iBp = pVCpu->dbgf.s.iActiveBp;
575 pVCpu->dbgf.s.iActiveBp = ~0U;
576 if (iBp != ~0U)
577 pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_RAW;
578 else
579 {
580 /* REM breakpoints has be been searched for. */
581#if 0 /** @todo get flat PC api! */
582 uint32_t eip = CPUMGetGuestEIP(pVM);
583#else
584 /* @todo SMP support!! */
585 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu(pVM));
586 RTGCPTR eip = pCtx->rip + pCtx->csHid.u64Base;
587#endif
588 for (iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); iBp++)
589 if ( pVM->dbgf.s.aBreakpoints[iBp].enmType == DBGFBPTYPE_REM
590 && pVM->dbgf.s.aBreakpoints[iBp].GCPtr == eip)
591 {
592 pVM->dbgf.s.DbgEvent.u.Bp.iBp = iBp;
593 break;
594 }
595 AssertMsg(pVM->dbgf.s.DbgEvent.u.Bp.iBp != ~0U, ("eip=%08x\n", eip));
596 pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_REM;
597 }
598 return dbgfR3SendEvent(pVM);
599}
600
601
602/**
603 * Waits for the debugger to respond.
604 *
605 * @returns VBox status. (clearify)
606 * @param pVM VM handle.
607 */
608static int dbgfR3VMMWait(PVM pVM)
609{
610 PVMCPU pVCpu = VMMGetCpu(pVM);
611
612 LogFlow(("dbgfR3VMMWait:\n"));
613
614 /** @todo stupid GDT/LDT sync hack. go away! */
615 SELMR3UpdateFromCPUM(pVM, pVCpu);
616 int rcRet = VINF_SUCCESS;
617
618 /*
619 * Waits for the debugger to reply (i.e. issue an command).
620 */
621 for (;;)
622 {
623 /*
624 * Wait.
625 */
626 uint32_t cPollHack = 1; /** @todo this interface is horrible now that we're using lots of VMR3ReqCall stuff all over DBGF. */
627 for (;;)
628 {
629 int rc;
630 if ( !VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_REQUEST)
631 && !VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_REQUEST))
632 {
633 rc = RTSemPingWait(&pVM->dbgf.s.PingPong, cPollHack);
634 if (RT_SUCCESS(rc))
635 break;
636 if (rc != VERR_TIMEOUT)
637 {
638 LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
639 return rc;
640 }
641 }
642
643 if (VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS))
644 {
645 rc = VMMR3EmtRendezvousFF(pVM, pVCpu);
646 cPollHack = 1;
647 }
648 else if ( VM_FF_ISPENDING(pVM, VM_FF_REQUEST)
649 || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_REQUEST))
650 {
651 LogFlow(("dbgfR3VMMWait: Processes requests...\n"));
652 rc = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY);
653 if (rc == VINF_SUCCESS)
654 rc = VMR3ReqProcessU(pVM->pUVM, pVCpu->idCpu);
655 LogFlow(("dbgfR3VMMWait: VMR3ReqProcess -> %Rrc rcRet=%Rrc\n", rc, rcRet));
656 cPollHack = 1;
657 }
658 else
659 {
660 rc = VINF_SUCCESS;
661 if (cPollHack < 120)
662 cPollHack++;
663 }
664
665 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
666 {
667 switch (rc)
668 {
669 case VINF_EM_DBG_BREAKPOINT:
670 case VINF_EM_DBG_STEPPED:
671 case VINF_EM_DBG_STEP:
672 case VINF_EM_DBG_STOP:
673 AssertMsgFailed(("rc=%Rrc\n", rc));
674 break;
675
676 /* return straight away */
677 case VINF_EM_TERMINATE:
678 case VINF_EM_OFF:
679 LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
680 return rc;
681
682 /* remember return code. */
683 default:
684 AssertReleaseMsgFailed(("rc=%Rrc is not in the switch!\n", rc));
685 case VINF_EM_RESET:
686 case VINF_EM_SUSPEND:
687 case VINF_EM_HALT:
688 case VINF_EM_RESUME:
689 case VINF_EM_RESCHEDULE:
690 case VINF_EM_RESCHEDULE_REM:
691 case VINF_EM_RESCHEDULE_RAW:
692 if (rc < rcRet || rcRet == VINF_SUCCESS)
693 rcRet = rc;
694 break;
695 }
696 }
697 else if (RT_FAILURE(rc))
698 {
699 LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rc));
700 return rc;
701 }
702 }
703
704 /*
705 * Process the command.
706 */
707 bool fResumeExecution;
708 DBGFCMDDATA CmdData = pVM->dbgf.s.VMMCmdData;
709 DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_NO_COMMAND);
710 int rc = dbgfR3VMMCmd(pVM, enmCmd, &CmdData, &fResumeExecution);
711 if (fResumeExecution)
712 {
713 if (RT_FAILURE(rc))
714 rcRet = rc;
715 else if ( rc >= VINF_EM_FIRST
716 && rc <= VINF_EM_LAST
717 && (rc < rcRet || rcRet == VINF_SUCCESS))
718 rcRet = rc;
719 LogFlow(("dbgfR3VMMWait: returns %Rrc\n", rcRet));
720 return rcRet;
721 }
722 }
723}
724
725
726/**
727 * Executes command from debugger.
728 * The caller is responsible for waiting or resuming execution based on the
729 * value returned in the *pfResumeExecution indicator.
730 *
731 * @returns VBox status. (clearify!)
732 * @param pVM VM Handle.
733 * @param enmCmd The command in question.
734 * @param pCmdData Pointer to the command data.
735 * @param pfResumeExecution Where to store the resume execution / continue waiting indicator.
736 */
737static int dbgfR3VMMCmd(PVM pVM, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution)
738{
739 bool fSendEvent;
740 bool fResume;
741 int rc = VINF_SUCCESS;
742
743 switch (enmCmd)
744 {
745 /*
746 * Halt is answered by an event say that we've halted.
747 */
748 case DBGFCMD_HALT:
749 {
750 pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_HALT_DONE;
751 pVM->dbgf.s.DbgEvent.enmCtx = dbgfR3FigureEventCtx(pVM);
752 fSendEvent = true;
753 fResume = false;
754 break;
755 }
756
757
758 /*
759 * Resume is not answered we'll just resume execution.
760 */
761 case DBGFCMD_GO:
762 {
763 fSendEvent = false;
764 fResume = true;
765 break;
766 }
767
768 /** @todo implement (and define) the rest of the commands. */
769
770 /*
771 * Disable breakpoints and stuff.
772 * Send an everythings cool event to the debugger thread and resume execution.
773 */
774 case DBGFCMD_DETACH_DEBUGGER:
775 {
776 ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, false);
777 pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_DETACH_DONE;
778 pVM->dbgf.s.DbgEvent.enmCtx = DBGFEVENTCTX_OTHER;
779 fSendEvent = true;
780 fResume = true;
781 break;
782 }
783
784 /*
785 * The debugger has detached successfully.
786 * There is no reply to this event.
787 */
788 case DBGFCMD_DETACHED_DEBUGGER:
789 {
790 fSendEvent = false;
791 fResume = true;
792 break;
793 }
794
795 /*
796 * Single step, with trace into.
797 */
798 case DBGFCMD_SINGLE_STEP:
799 {
800 Log2(("Single step\n"));
801 rc = VINF_EM_DBG_STEP;
802 /** @todo SMP */
803 PVMCPU pVCpu = VMMGetCpu0(pVM);
804 pVCpu->dbgf.s.fSingleSteppingRaw = true;
805 fSendEvent = false;
806 fResume = true;
807 break;
808 }
809
810 /*
811 * Default is to send an invalid command event.
812 */
813 default:
814 {
815 pVM->dbgf.s.DbgEvent.enmType = DBGFEVENT_INVALID_COMMAND;
816 pVM->dbgf.s.DbgEvent.enmCtx = dbgfR3FigureEventCtx(pVM);
817 fSendEvent = true;
818 fResume = false;
819 break;
820 }
821 }
822
823 /*
824 * Send pending event.
825 */
826 if (fSendEvent)
827 {
828 Log2(("DBGF: Emulation thread: sending event %d\n", pVM->dbgf.s.DbgEvent.enmType));
829 int rc2 = RTSemPing(&pVM->dbgf.s.PingPong);
830 if (RT_FAILURE(rc2))
831 {
832 AssertRC(rc2);
833 *pfResumeExecution = true;
834 return rc2;
835 }
836 }
837
838 /*
839 * Return.
840 */
841 *pfResumeExecution = fResume;
842 return rc;
843}
844
845
846/**
847 * Attaches a debugger to the specified VM.
848 *
849 * Only one debugger at a time.
850 *
851 * @returns VBox status code.
852 * @param pVM VM Handle.
853 */
854VMMR3DECL(int) DBGFR3Attach(PVM pVM)
855{
856 /*
857 * Some validations first.
858 */
859 if (!VALID_PTR(pVM))
860 {
861 Log(("DBGFR3Attach: bad VM handle: %p\n", pVM));
862 return VERR_INVALID_HANDLE;
863 }
864 VMSTATE enmVMState = pVM->enmVMState;
865 if ( enmVMState >= VMSTATE_DESTROYING
866 || enmVMState < VMSTATE_CREATING)
867 {
868 Log(("DBGFR3Attach: Invalid VM state: %s\n", VMGetStateName(enmVMState)));
869 return VERR_INVALID_HANDLE;
870 }
871
872 /*
873 * Call the VM, use EMT for serialization.
874 */
875 /** @todo SMP */
876 return VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)dbgfR3Attach, 1, pVM);
877}
878
879
880/**
881 * EMT worker for DBGFR3Attach.
882 *
883 * @returns VBox status code.
884 * @param pVM Pointer to the shared VM structure.
885 */
886static DECLCALLBACK(int) dbgfR3Attach(PVM pVM)
887{
888 if (pVM->dbgf.s.fAttached)
889 {
890 Log(("dbgR3Attach: Debugger already attached\n"));
891 return VERR_DBGF_ALREADY_ATTACHED;
892 }
893
894 /*
895 * Create the Ping-Pong structure.
896 */
897 int rc = RTSemPingPongInit(&pVM->dbgf.s.PingPong);
898 AssertRCReturn(rc, rc);
899
900 /*
901 * Set the attached flag.
902 */
903 ASMAtomicWriteBool(&pVM->dbgf.s.fAttached, true);
904 return VINF_SUCCESS;
905}
906
907
908/**
909 * Detaches a debugger from the specified VM.
910 *
911 * Caller must be attached to the VM.
912 *
913 * @returns VBox status code.
914 * @param pVM VM Handle.
915 */
916VMMR3DECL(int) DBGFR3Detach(PVM pVM)
917{
918 LogFlow(("DBGFR3Detach:\n"));
919 int rc;
920
921 /*
922 * Check if attached.
923 */
924 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
925
926 /*
927 * Try send the detach command.
928 * Keep in mind that we might be racing EMT, so, be extra careful.
929 */
930 DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_DETACH_DEBUGGER);
931 if (RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong))
932 {
933 rc = RTSemPong(&pVM->dbgf.s.PingPong);
934 AssertMsgRCReturn(rc, ("Failed to signal emulation thread. rc=%Rrc\n", rc), rc);
935 LogRel(("DBGFR3Detach: enmCmd=%d (pong -> ping)\n", enmCmd));
936 }
937
938 /*
939 * Wait for the OK event.
940 */
941 rc = RTSemPongWait(&pVM->dbgf.s.PingPong, RT_INDEFINITE_WAIT);
942 AssertLogRelMsgRCReturn(rc, ("Wait on detach command failed, rc=%Rrc\n", rc), rc);
943
944 /*
945 * Send the notification command indicating that we're really done.
946 */
947 enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_DETACHED_DEBUGGER);
948 rc = RTSemPong(&pVM->dbgf.s.PingPong);
949 AssertMsgRCReturn(rc, ("Failed to signal emulation thread. rc=%Rrc\n", rc), rc);
950
951 LogFlowFunc(("returns VINF_SUCCESS\n"));
952 return VINF_SUCCESS;
953}
954
955
956/**
957 * Wait for a debug event.
958 *
959 * @returns VBox status. Will not return VBOX_INTERRUPTED.
960 * @param pVM VM handle.
961 * @param cMillies Number of millis to wait.
962 * @param ppEvent Where to store the event pointer.
963 */
964VMMR3DECL(int) DBGFR3EventWait(PVM pVM, RTMSINTERVAL cMillies, PCDBGFEVENT *ppEvent)
965{
966 /*
967 * Check state.
968 */
969 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
970 *ppEvent = NULL;
971
972 /*
973 * Wait.
974 */
975 int rc = RTSemPongWait(&pVM->dbgf.s.PingPong, cMillies);
976 if (RT_SUCCESS(rc))
977 {
978 *ppEvent = &pVM->dbgf.s.DbgEvent;
979 Log2(("DBGF: Debugger thread: receiving event %d\n", (*ppEvent)->enmType));
980 return VINF_SUCCESS;
981 }
982
983 return rc;
984}
985
986
987/**
988 * Halts VM execution.
989 *
990 * After calling this the VM isn't actually halted till an DBGFEVENT_HALT_DONE
991 * arrives. Until that time it's not possible to issue any new commands.
992 *
993 * @returns VBox status.
994 * @param pVM VM handle.
995 */
996VMMR3DECL(int) DBGFR3Halt(PVM pVM)
997{
998 /*
999 * Check state.
1000 */
1001 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
1002 RTPINGPONGSPEAKER enmSpeaker = pVM->dbgf.s.PingPong.enmSpeaker;
1003 if ( enmSpeaker == RTPINGPONGSPEAKER_PONG
1004 || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED)
1005 return VWRN_DBGF_ALREADY_HALTED;
1006
1007 /*
1008 * Send command.
1009 */
1010 dbgfR3SetCmd(pVM, DBGFCMD_HALT);
1011
1012 return VINF_SUCCESS;
1013}
1014
1015
1016/**
1017 * Checks if the VM is halted by the debugger.
1018 *
1019 * @returns True if halted.
1020 * @returns False if not halted.
1021 * @param pVM VM handle.
1022 */
1023VMMR3DECL(bool) DBGFR3IsHalted(PVM pVM)
1024{
1025 AssertReturn(pVM->dbgf.s.fAttached, false);
1026 RTPINGPONGSPEAKER enmSpeaker = pVM->dbgf.s.PingPong.enmSpeaker;
1027 return enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED
1028 || enmSpeaker == RTPINGPONGSPEAKER_PONG;
1029}
1030
1031
1032/**
1033 * Checks if the debugger can wait for events or not.
1034 *
1035 * This function is only used by lazy, multiplexing debuggers. :-)
1036 *
1037 * @returns True if waitable.
1038 * @returns False if not waitable.
1039 * @param pVM VM handle.
1040 */
1041VMMR3DECL(bool) DBGFR3CanWait(PVM pVM)
1042{
1043 AssertReturn(pVM->dbgf.s.fAttached, false);
1044 return RTSemPongShouldWait(&pVM->dbgf.s.PingPong);
1045}
1046
1047
1048/**
1049 * Resumes VM execution.
1050 *
1051 * There is no receipt event on this command.
1052 *
1053 * @returns VBox status.
1054 * @param pVM VM handle.
1055 */
1056VMMR3DECL(int) DBGFR3Resume(PVM pVM)
1057{
1058 /*
1059 * Check state.
1060 */
1061 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
1062 AssertReturn(RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong), VERR_SEM_OUT_OF_TURN);
1063
1064 /*
1065 * Send the ping back to the emulation thread telling it to run.
1066 */
1067 dbgfR3SetCmd(pVM, DBGFCMD_GO);
1068 int rc = RTSemPong(&pVM->dbgf.s.PingPong);
1069 AssertRC(rc);
1070
1071 return rc;
1072}
1073
1074
1075/**
1076 * Step Into.
1077 *
1078 * A single step event is generated from this command.
1079 * The current implementation is not reliable, so don't rely on the event coming.
1080 *
1081 * @returns VBox status.
1082 * @param pVM VM handle.
1083 * @param idCpu The ID of the CPU to single step on.
1084 */
1085VMMR3DECL(int) DBGFR3Step(PVM pVM, VMCPUID idCpu)
1086{
1087 /*
1088 * Check state.
1089 */
1090 AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);
1091 AssertReturn(RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong), VERR_SEM_OUT_OF_TURN);
1092 AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_PARAMETER);
1093
1094 /*
1095 * Send the ping back to the emulation thread telling it to run.
1096 */
1097/** @todo SMP (idCpu) */
1098 dbgfR3SetCmd(pVM, DBGFCMD_SINGLE_STEP);
1099 int rc = RTSemPong(&pVM->dbgf.s.PingPong);
1100 AssertRC(rc);
1101 return rc;
1102}
1103
1104
1105/**
1106 * Call this to single step programmatically.
1107 *
1108 * You must pass down the return code to the EM loop! That's
1109 * where the actual single stepping take place (at least in the
1110 * current implementation).
1111 *
1112 * @returns VINF_EM_DBG_STEP
1113 *
1114 * @param pVCpu The virtual CPU handle.
1115 *
1116 * @thread VCpu EMT
1117 */
1118VMMR3DECL(int) DBGFR3PrgStep(PVMCPU pVCpu)
1119{
1120 VMCPU_ASSERT_EMT(pVCpu);
1121
1122 pVCpu->dbgf.s.fSingleSteppingRaw = true;
1123 return VINF_EM_DBG_STEP;
1124}
1125
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