summaryrefslogtreecommitdiff
path: root/src/VBox/Debugger/DBGCEmulateCodeView.cpp
diff options
context:
space:
mode:
authorvboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2016-11-20 02:02:27 +0000
committervboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2016-11-20 02:02:27 +0000
commit7c105254c53bfa9277155ff231a6e2ed8c20bf66 (patch)
tree24359ab8bcfa929b5e52dcc546f27a8a583ba64f /src/VBox/Debugger/DBGCEmulateCodeView.cpp
parentd44cb254de540b1dad59d55bb7089cc4b2176ef6 (diff)
downloadVirtualBox-svn-7c105254c53bfa9277155ff231a6e2ed8c20bf66.tar.gz
DBGC: Basic implementation of the 'gu' (shift-F11), 'p' (F10), 'pc', 'pt', 'tc', 'tt' commands as well as 'tr/pr' variant.
git-svn-id: https://www.virtualbox.org/svn/vbox/trunk@64721 cfe28804-0f27-0410-a406-dd0f0b0b656f
Diffstat (limited to 'src/VBox/Debugger/DBGCEmulateCodeView.cpp')
-rw-r--r--src/VBox/Debugger/DBGCEmulateCodeView.cpp134
1 files changed, 126 insertions, 8 deletions
diff --git a/src/VBox/Debugger/DBGCEmulateCodeView.cpp b/src/VBox/Debugger/DBGCEmulateCodeView.cpp
index 9c99f6a0581..26131242edf 100644
--- a/src/VBox/Debugger/DBGCEmulateCodeView.cpp
+++ b/src/VBox/Debugger/DBGCEmulateCodeView.cpp
@@ -64,6 +64,7 @@ static FNDBGCCMD dbgcCmdDumpTypeInfo;
static FNDBGCCMD dbgcCmdDumpTypedVal;
static FNDBGCCMD dbgcCmdEditMem;
static FNDBGCCMD dbgcCmdGo;
+static FNDBGCCMD dbgcCmdGoUp;
static FNDBGCCMD dbgcCmdListModules;
static FNDBGCCMD dbgcCmdListNear;
static FNDBGCCMD dbgcCmdListSource;
@@ -74,11 +75,13 @@ static FNDBGCCMD dbgcCmdRegHyper;
static FNDBGCCMD dbgcCmdRegTerse;
static FNDBGCCMD dbgcCmdSearchMem;
static FNDBGCCMD dbgcCmdSearchMemType;
+static FNDBGCCMD dbgcCmdStepTrace;
+static FNDBGCCMD dbgcCmdStepTraceTo;
+static FNDBGCCMD dbgcCmdStepTraceToggle;
static FNDBGCCMD dbgcCmdEventCtrl;
static FNDBGCCMD dbgcCmdEventCtrlList;
static FNDBGCCMD dbgcCmdEventCtrlReset;
static FNDBGCCMD dbgcCmdStack;
-static FNDBGCCMD dbgcCmdTrace;
static FNDBGCCMD dbgcCmdUnassemble;
static FNDBGCCMD dbgcCmdUnassembleCfg;
@@ -268,6 +271,24 @@ static const DBGCVARDESC g_aArgMemoryInfo[] =
};
+/** 'p', 'pc', 'pt', 't', 'tc' and 'tt' arguments. */
+static const DBGCVARDESC g_aArgStepTrace[] =
+{
+ /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
+ { 0, 1, DBGCVAR_CAT_NUMBER, 0, "count", "Number of instructions or source lines to step." },
+ { 0, 1, DBGCVAR_CAT_STRING, 0, "cmds", "String of commands to be executed afterwards. Quote it!" },
+};
+
+
+/** 'pa' and 'ta' arguments. */
+static const DBGCVARDESC g_aArgStepTraceTo[] =
+{
+ /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
+ { 1, 1, DBGCVAR_CAT_POINTER, 0, "address", "Where to stop" },
+ { 0, 1, DBGCVAR_CAT_STRING, 0, "cmds", "String of commands to be executed afterwards. Quote it!" },
+};
+
+
/** 'r' arguments. */
static const DBGCVARDESC g_aArgReg[] =
{
@@ -389,6 +410,7 @@ const DBGCCMD g_aCmdsCodeView[] =
{ "ed", 2, 2, &g_aArgEditMem[0], RT_ELEMENTS(g_aArgEditMem), 0, dbgcCmdEditMem, "<addr> <value>", "Write a 4-byte value to memory." },
{ "eq", 2, 2, &g_aArgEditMem[0], RT_ELEMENTS(g_aArgEditMem), 0, dbgcCmdEditMem, "<addr> <value>", "Write a 8-byte value to memory." },
{ "g", 0, 0, NULL, 0, 0, dbgcCmdGo, "", "Continue execution." },
+ { "gu", 0, 0, NULL, 0, 0, dbgcCmdGoUp, "", "Go up - continue execution till after return." },
{ "k", 0, 0, NULL, 0, 0, dbgcCmdStack, "", "Callstack." },
{ "kg", 0, 0, NULL, 0, 0, dbgcCmdStack, "", "Callstack - guest." },
{ "kh", 0, 0, NULL, 0, 0, dbgcCmdStack, "", "Callstack - hypervisor." },
@@ -399,6 +421,11 @@ const DBGCCMD g_aCmdsCodeView[] =
{ "ln", 0, ~0U, &g_aArgListNear[0], RT_ELEMENTS(g_aArgListNear), 0, dbgcCmdListNear, "[addr/sym [..]]", "List symbols near to the address. Default address is CS:EIP." },
{ "ls", 0, 1, &g_aArgListSource[0],RT_ELEMENTS(g_aArgListSource), 0, dbgcCmdListSource, "[addr]", "Source." },
{ "m", 1, 1, &g_aArgMemoryInfo[0],RT_ELEMENTS(g_aArgMemoryInfo), 0, dbgcCmdMemoryInfo, "<addr>", "Display information about that piece of memory." },
+ { "p", 0, 2, &g_aArgStepTrace[0], RT_ELEMENTS(g_aArgStepTrace), 0, dbgcCmdStepTrace, "[count] [cmds]", "Step over." },
+ { "pr", 0, 0, NULL, 0, 0, dbgcCmdStepTraceToggle, "", "Toggle displaying registers for tracing & stepping (no code executed)." },
+ { "pa", 1, 1, &g_aArgStepTraceTo[0], RT_ELEMENTS(g_aArgStepTraceTo), 0, dbgcCmdStepTraceTo, "<addr> [count] [cmds]","Step to the given address." },
+ { "pc", 0, 0, &g_aArgStepTrace[0], RT_ELEMENTS(g_aArgStepTrace), 0, dbgcCmdStepTrace, "[count] [cmds]", "Step to the next call instruction." },
+ { "pt", 0, 0, &g_aArgStepTrace[0], RT_ELEMENTS(g_aArgStepTrace), 0, dbgcCmdStepTrace, "[count] [cmds]", "Step to the next return instruction." },
{ "r", 0, 3, &g_aArgReg[0], RT_ELEMENTS(g_aArgReg), 0, dbgcCmdReg, "[reg [[=] newval]]", "Show or set register(s) - active reg set." },
{ "rg", 0, 3, &g_aArgReg[0], RT_ELEMENTS(g_aArgReg), 0, dbgcCmdRegGuest, "[reg [[=] newval]]", "Show or set register(s) - guest reg set." },
{ "rg32", 0, 0, NULL, 0, 0, dbgcCmdRegGuest, "", "Show 32-bit guest registers." },
@@ -418,7 +445,11 @@ const DBGCCMD g_aCmdsCodeView[] =
{ "sxn", 1, ~0U, &g_aArgEventCtrl[0], RT_ELEMENTS(g_aArgEventCtrl), 0, dbgcCmdEventCtrl, "[-c <cmd>] <event> [..]", "Notify: Display info in the debugger and continue on the specified exceptions, exits and other events. 'all' addresses all." },
{ "sxi", 1, ~0U, &g_aArgEventCtrl[0], RT_ELEMENTS(g_aArgEventCtrl), 0, dbgcCmdEventCtrl, "[-c <cmd>] <event> [..]", "Ignore: Ignore the specified exceptions, exits and other events ('all' = all of them). Without the -c option, the guest runs like normal." },
{ "sxr", 0, 0, &g_aArgEventCtrlOpt[0], RT_ELEMENTS(g_aArgEventCtrlOpt), 0, dbgcCmdEventCtrlReset, "", "Reset the settings to default for exceptions, exits and other events. All if no filter is specified." },
- { "t", 0, 0, NULL, 0, 0, dbgcCmdTrace, "", "Instruction trace (step into)." },
+ { "t", 0, 2, &g_aArgStepTrace[0], RT_ELEMENTS(g_aArgStepTrace), 0, dbgcCmdStepTrace, "[count] [cmds]", "Trace ." },
+ { "tr", 0, 0, NULL, 0, 0, dbgcCmdStepTraceToggle, "", "Toggle displaying registers for tracing & stepping (no code executed)." },
+ { "ta", 1, 1, &g_aArgStepTraceTo[0], RT_ELEMENTS(g_aArgStepTraceTo), 0, dbgcCmdStepTraceTo, "<addr> [count] [cmds]","Trace to the given address." },
+ { "tc", 0, 0, &g_aArgStepTrace[0], RT_ELEMENTS(g_aArgStepTrace), 0, dbgcCmdStepTrace, "[count] [cmds]", "Trace to the next call instruction." },
+ { "tt", 0, 0, &g_aArgStepTrace[0], RT_ELEMENTS(g_aArgStepTrace), 0, dbgcCmdStepTrace, "[count] [cmds]", "Trace to the next return instruction." },
{ "u", 0, 1, &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble), 0, dbgcCmdUnassemble, "[addr]", "Unassemble." },
{ "u64", 0, 1, &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble), 0, dbgcCmdUnassemble, "[addr]", "Unassemble 64-bit code." },
{ "u32", 0, 1, &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble), 0, dbgcCmdUnassemble, "[addr]", "Unassemble 32-bit code." },
@@ -594,7 +625,7 @@ const uint32_t g_cDbgcSxEvents = RT_ELEMENTS(g_aDbgcSxEvents);
/**
- * @callback_method_impl{FNDBGCCMD, The 'go' command.}
+ * @callback_method_impl{FNDBGCCMD, The 'g' command.}
*/
static DECLCALLBACK(int) dbgcCmdGo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
{
@@ -616,6 +647,26 @@ static DECLCALLBACK(int) dbgcCmdGo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUV
/**
+ * @callback_method_impl{FNDBGCCMD, The 'gu' command.}
+ */
+static DECLCALLBACK(int) dbgcCmdGoUp(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
+{
+ PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
+ RT_NOREF(pCmd, paArgs, cArgs);
+
+ /* The simple way out. */
+ PDBGFADDRESS pStackPop = NULL; /** @todo try set up some stack limitations */
+ RTGCPTR cbStackPop = 0;
+ int rc = DBGFR3StepEx(pUVM, pDbgc->idCpu, DBGF_STEP_F_OVER | DBGF_STEP_F_STOP_AFTER_RET, NULL, pStackPop, cbStackPop, _512K);
+ if (RT_SUCCESS(rc))
+ pDbgc->fReady = false;
+ else
+ return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3StepEx(,,DBGF_STEP_F_OVER | DBGF_STEP_F_STOP_AFTER_RET,) failed");
+ return rc;
+}
+
+
+/**
* @callback_method_impl{FNDBGCCMD, The 'ba' command.}
*/
static DECLCALLBACK(int) dbgcCmdBrkAccess(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
@@ -2482,7 +2533,7 @@ static DECLCALLBACK(int) dbgcCmdRegGuest(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PU
/*
* Disassemble one instruction at cs:[r|e]ip.
*/
- if (!f64BitMode && strstr(pszRegs, " vm ")) /* a big ugly... */
+ if (!f64BitMode && strstr(pszRegs, " vm ")) /* a bit ugly... */
return pCmdHlp->pfnExec(pCmdHlp, "uv86 %s", szDisAndRegs + 2);
return pCmdHlp->pfnExec(pCmdHlp, "%s", szDisAndRegs);
}
@@ -2554,17 +2605,59 @@ static DECLCALLBACK(int) dbgcCmdRegTerse(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PU
/**
- * @callback_method_impl{FNDBGCCMD, The 't' command.}
+ * @callback_method_impl{FNDBGCCMD, The 'pr' and 'tr' commands.}
*/
-static DECLCALLBACK(int) dbgcCmdTrace(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
+static DECLCALLBACK(int) dbgcCmdStepTraceToggle(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
+{
+ PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
+ Assert(cArgs == 0); NOREF(pCmd); NOREF(pUVM); NOREF(paArgs); NOREF(cArgs);
+
+ /* Note! windbg accepts 'r' as a flag to 'p', 'pa', 'pc', 'pt', 't',
+ 'ta', 'tc' and 'tt'. We've simplified it. */
+ pDbgc->fStepTraceRegs = !pDbgc->fStepTraceRegs;
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNDBGCCMD,
+ * The 'p', 'pc', 'pt', 't', 'tc', and 'tt' commands.}
+ */
+static DECLCALLBACK(int) dbgcCmdStepTrace(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
{
PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
+ if (cArgs != 0)
+ return DBGCCmdHlpFail(pCmdHlp, pCmd,
+ "Sorry, but the '%s' command does not currently implement any arguments.\n", pCmd->pszCmd);
+
+ /* The 'count' has to be implemented by DBGC, whereas the
+ filtering is taken care of by DBGF. */
- int rc = DBGFR3Step(pUVM, pDbgc->idCpu);
+ /*
+ * Convert the command to DBGF_STEP_F_XXX and other API input.
+ */
+ //DBGFADDRESS StackPop;
+ PDBGFADDRESS pStackPop = NULL;
+ RTGCPTR cbStackPop = 0;
+ uint32_t cMaxSteps = pCmd->pszCmd[0] == 'p' ? _512K : _64K;
+ uint32_t fFlags = pCmd->pszCmd[0] == 'p' ? DBGF_STEP_F_OVER : DBGF_STEP_F_INTO;
+ if (pCmd->pszCmd[1] == 'c')
+ fFlags |= DBGF_STEP_F_STOP_ON_CALL;
+ else if (pCmd->pszCmd[1] == 't')
+ fFlags |= DBGF_STEP_F_STOP_ON_RET;
+ else if (pCmd->pszCmd[0] != 'p')
+ cMaxSteps = 1;
+ else
+ {
+ /** @todo consider passing RSP + 1 in for 'p' and something else sensible for
+ * the 'pt' command. */
+ }
+
+ int rc = DBGFR3StepEx(pUVM, pDbgc->idCpu, fFlags, NULL, pStackPop, cbStackPop, cMaxSteps);
if (RT_SUCCESS(rc))
pDbgc->fReady = false;
else
- rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "When trying to single step VM %p\n", pDbgc->pVM);
+ return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3StepEx(,,%#x,) failed", fFlags);
NOREF(pCmd); NOREF(paArgs); NOREF(cArgs);
return rc;
@@ -2572,6 +2665,31 @@ static DECLCALLBACK(int) dbgcCmdTrace(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM
/**
+ * @callback_method_impl{FNDBGCCMD, The 'pa' and 'ta' commands.}
+ */
+static DECLCALLBACK(int) dbgcCmdStepTraceTo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
+{
+ PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
+ if (cArgs != 1)
+ return DBGCCmdHlpFail(pCmdHlp, pCmd,
+ "Sorry, but the '%s' command only implements a single argument at present.\n", pCmd->pszCmd);
+ DBGFADDRESS Address;
+ int rc = pCmdHlp->pfnVarToDbgfAddr(pCmdHlp, &paArgs[0], &Address);
+ if (RT_FAILURE(rc))
+ return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "VarToDbgfAddr(,%Dv,)\n", &paArgs[0]);
+
+ uint32_t cMaxSteps = pCmd->pszCmd[0] == 'p' ? _512K : 1;
+ uint32_t fFlags = pCmd->pszCmd[0] == 'p' ? DBGF_STEP_F_OVER : DBGF_STEP_F_INTO;
+ rc = DBGFR3StepEx(pUVM, pDbgc->idCpu, fFlags, &Address, NULL, 0, cMaxSteps);
+ if (RT_SUCCESS(rc))
+ pDbgc->fReady = false;
+ else
+ return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3StepEx(,,%#x,) failed", fFlags);
+ return rc;
+}
+
+
+/**
* @callback_method_impl{FNDBGCCMD, The 'k'\, 'kg' and 'kh' commands.}
*/
static DECLCALLBACK(int) dbgcCmdStack(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)