DBGF.cpp revision 90ecd36a6e45ec33526541f68cf89c21ec578f83
181e56d8b348d301d615ccf5465ae600fee2867berikabele * DBGF - Debugger Facility.
5a58787efeb02a1c3f06569d019ad81fd2efa06end * Copyright (C) 2006-2007 Oracle Corporation
5a58787efeb02a1c3f06569d019ad81fd2efa06end * This file is part of VirtualBox Open Source Edition (OSE), as
5a58787efeb02a1c3f06569d019ad81fd2efa06end * available from http://www.virtualbox.org. This file is free software;
5a58787efeb02a1c3f06569d019ad81fd2efa06end * you can redistribute it and/or modify it under the terms of the GNU
5a58787efeb02a1c3f06569d019ad81fd2efa06end * General Public License (GPL) as published by the Free Software
5a58787efeb02a1c3f06569d019ad81fd2efa06end * Foundation, in version 2 as it comes in the "COPYING" file of the
5a58787efeb02a1c3f06569d019ad81fd2efa06end * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
52fff662005b1866a3ff09bb6c902800c5cc6dedjerenkrantz * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4b5981e276e93df97c34e4da05ca5cf8bbd937dand/** @page pg_dbgf DBGF - The Debugger Facility
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd * The purpose of the DBGF is to provide an interface for debuggers to
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd * manipulate the VMM without having to mess up the source code for each of
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd * them. The DBGF is always built in and will always work when a debugger
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * attaches to the VM. The DBGF provides the basic debugger features, such as
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * halting execution, handling breakpoints, single step execution, instruction
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * disassembly, info querying, OS specific diggers, symbol and module
181e56d8b348d301d615ccf5465ae600fee2867berikabele * management.
5a58787efeb02a1c3f06569d019ad81fd2efa06end * The interface is working in a manner similar to the win32, linux and os2
5a58787efeb02a1c3f06569d019ad81fd2efa06end * debugger interfaces. The interface has an asynchronous nature. This comes
5a58787efeb02a1c3f06569d019ad81fd2efa06end * from the fact that the VMM and the Debugger are running in different threads.
5a58787efeb02a1c3f06569d019ad81fd2efa06end * They are referred to as the "emulation thread" and the "debugger thread", or
5a58787efeb02a1c3f06569d019ad81fd2efa06end * as the "ping thread" and the "pong thread, respectivly. (The last set of
5a58787efeb02a1c3f06569d019ad81fd2efa06end * names comes from the use of the Ping-Pong synchronization construct from the
5a58787efeb02a1c3f06569d019ad81fd2efa06end * RTSem API.)
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * @see grp_dbgf
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * @section sec_dbgf_scenario Usage Scenario
181e56d8b348d301d615ccf5465ae600fee2867berikabele * The debugger starts by attaching to the VM. For practical reasons we limit the
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * number of concurrently attached debuggers to 1 per VM. The action of
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * attaching to the VM causes the VM to check and generate debug events.
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * The debugger then will wait/poll for debug events and issue commands.
a38b5f73e7f0f3b8726fb47d27b145f37036ead0jim * The waiting and polling is done by the DBGFEventWait() function. It will wait
a38b5f73e7f0f3b8726fb47d27b145f37036ead0jim * for the emulation thread to send a ping, thus indicating that there is an
a38b5f73e7f0f3b8726fb47d27b145f37036ead0jim * event waiting to be processed.
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * An event can be a response to a command issued previously, the hitting of a
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * breakpoint, or running into a bad/fatal VMM condition. The debugger now has
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * the ping and must respond to the event at hand - the VMM is waiting. This
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * usually means that the user of the debugger must do something, but it doesn't
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * have to. The debugger is free to call any DBGF function (nearly at least)
5a58787efeb02a1c3f06569d019ad81fd2efa06end * while processing the event.
5a58787efeb02a1c3f06569d019ad81fd2efa06end * Typically the user will issue a request for the execution to be resumed, so
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele * the debugger calls DBGFResume() and goes back to waiting/polling for events.
181e56d8b348d301d615ccf5465ae600fee2867berikabele * When the user eventually terminates the debugging session or selects another
57d0156f7bbd9ea3a72342cf9912aba61d118702rbowen * VM, the debugger detaches from the VM. This means that breakpoints are
57d0156f7bbd9ea3a72342cf9912aba61d118702rbowen * disabled and that the emulation thread no longer polls for debugger commands.
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele/*******************************************************************************
c8e71fab0ea4bc3f8cb07693d6917f6b4644fbdcerikabele* Header Files *
5a58787efeb02a1c3f06569d019ad81fd2efa06end*******************************************************************************/
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd/*******************************************************************************
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd* Internal Functions *
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd*******************************************************************************/
b95ae799514ad86a15610ad75808d7065e9847c9kessstatic int dbgfR3VMMCmd(PVM pVM, DBGFCMD enmCmd, PDBGFCMDDATA pCmdData, bool *pfResumeExecution);
AssertMsg(pVM->dbgf.s.enmVMMCmd == DBGFCMD_NO_COMMAND, ("enmCmd=%d enmVMMCmd=%d\n", enmCmd, pVM->dbgf.s.enmVMMCmd));
return rc;
return rc;
int rc;
bool fResumeExecution;
return VINF_SUCCESS;
#ifndef RT_OS_L4
# if !defined(DEBUG) || defined(DEBUG_sandervl) || defined(DEBUG_frank) || defined(IEM_VERIFICATION_MODE)
RTStrmPrintf(g_pStdErr, "DBGF: No debugger attached, waiting %d second%s for one to attach (event=%d)\n",
while (cWait > 0)
cWait--;
bool fResumeExecution;
if (!fResumeExecution)
return rc;
switch (enmEvent)
case DBGFEVENT_STEPPED_HYPER:
case EMSTATE_RAW:
case EMSTATE_DEBUG_GUEST_RAW:
return DBGFEVENTCTX_RAW;
case EMSTATE_REM:
case EMSTATE_DEBUG_GUEST_REM:
return DBGFEVENTCTX_REM;
case EMSTATE_DEBUG_HYPER:
case EMSTATE_GURU_MEDITATION:
return DBGFEVENTCTX_HYPER;
return DBGFEVENTCTX_OTHER;
return VERR_DBGF_NOT_ATTACHED;
#ifdef VBOX_WITH_REM
return VINF_SUCCESS;
/** @todo sync VMM -> REM after exitting the debugger. everything may change while in the debugger! */
return rc;
return rc;
VMMR3DECL(int) DBGFR3EventSrc(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, ...)
return rc;
VMMR3DECL(int) DBGFR3EventSrcV(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, va_list args)
return rc;
VMMR3DECL(int) DBGFR3EventAssertion(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszMsg1, const char *pszMsg2)
return rc;
return rc;
if (iBp != ~0U)
uint32_t cPollHack = 1; /** @todo this interface is horrible now that we're using lots of VMR3ReqCall stuff all over DBGF. */
int rc;
return rc;
cPollHack++;
switch (rc)
case VINF_EM_DBG_BREAKPOINT:
case VINF_EM_DBG_STEPPED:
case VINF_EM_DBG_STEP:
case VINF_EM_DBG_STOP:
case VINF_EM_TERMINATE:
case VINF_EM_OFF:
return rc;
case VINF_EM_RESET:
case VINF_EM_SUSPEND:
case VINF_EM_HALT:
case VINF_EM_RESUME:
case VINF_EM_RESCHEDULE:
case VINF_EM_RESCHEDULE_REM:
case VINF_EM_RESCHEDULE_RAW:
return rc;
bool fResumeExecution;
if (fResumeExecution)
return rcRet;
bool fSendEvent;
bool fResume;
switch (enmCmd)
case DBGFCMD_HALT:
fSendEvent = true;
fResume = false;
case DBGFCMD_GO:
fSendEvent = false;
fResume = true;
case DBGFCMD_DETACH_DEBUGGER:
fSendEvent = true;
fResume = true;
fSendEvent = false;
fResume = true;
case DBGFCMD_SINGLE_STEP:
fSendEvent = false;
fResume = true;
fSendEvent = true;
fResume = false;
if (fSendEvent)
*pfResumeExecution = true;
return rc2;
return rc;
return VERR_DBGF_ALREADY_ATTACHED;
return VINF_SUCCESS;
int rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
return VWRN_DBGF_ALREADY_HALTED;
return VINF_SUCCESS;
return rc;
return rc;
return VINF_EM_DBG_STEP;