DBGCEmulateCodeView.cpp revision 5c4ba9dc4a0f6857f3ca4ff896fa1d03e3b2d830
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * DBGC - Debugger Console, CodeView / WinDbg Emulation.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Copyright (C) 2006-2013 Oracle Corporation
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * This file is part of VirtualBox Open Source Edition (OSE), as
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * available from http://www.virtualbox.org. This file is free software;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * you can redistribute it and/or modify it under the terms of the GNU
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * General Public License (GPL) as published by the Free Software
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Foundation, in version 2 as it comes in the "COPYING" file of the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk/*******************************************************************************
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk* Header Files *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk*******************************************************************************/
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/*******************************************************************************
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk* Internal Functions *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk*******************************************************************************/
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/*******************************************************************************
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk* Global Variables *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk*******************************************************************************/
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'ba' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, 1, DBGCVAR_CAT_STRING, 0, "access", "The access type: x=execute, rw=read/write (alias r), w=write, i=not implemented." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, 1, DBGCVAR_CAT_NUMBER, 0, "size", "The access size: 1, 2, 4, or 8. 'x' access requires 1, and 8 requires amd64 long mode." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, 1, DBGCVAR_CAT_GC_POINTER, 0, "address", "The address." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_NUMBER, 0, "passes", "The number of passes before we trigger the breakpoint. (0 is default)" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_NUMBER, DBGCVD_FLAGS_DEP_PREV, "max passes", "The number of passes after which we stop triggering the breakpoint. (~0 is default)" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_STRING, 0, "cmds", "String of commands to be executed when the breakpoint is hit. Quote it!" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'bc', 'bd', 'be' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, ~0U, DBGCVAR_CAT_NUMBER, 0, "#bp", "Breakpoint number." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_STRING, 0, "all", "All breakpoints." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'bp' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, 1, DBGCVAR_CAT_GC_POINTER, 0, "address", "The address." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_NUMBER, 0, "passes", "The number of passes before we trigger the breakpoint. (0 is default)" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_NUMBER, DBGCVD_FLAGS_DEP_PREV, "max passes", "The number of passes after which we stop triggering the breakpoint. (~0 is default)" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_STRING, 0, "cmds", "String of commands to be executed when the breakpoint is hit. Quote it!" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'br' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, 1, DBGCVAR_CAT_GC_POINTER, 0, "address", "The address." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_NUMBER, 0, "passes", "The number of passes before we trigger the breakpoint. (0 is default)" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_NUMBER, DBGCVD_FLAGS_DEP_PREV, "max passes", "The number of passes after which we stop triggering the breakpoint. (~0 is default)" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_STRING, 0, "cmds", "String of commands to be executed when the breakpoint is hit. Quote it!" },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'd?' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address where to start dumping memory." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'dg', 'dga', 'dl', 'dla' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, ~0U, DBGCVAR_CAT_NUMBER, 0, "sel", "Selector or selector range." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, ~0U, DBGCVAR_CAT_POINTER, 0, "address", "Far address which selector should be dumped." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'di', 'dia' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, ~0U, DBGCVAR_CAT_NUMBER, 0, "int", "The interrupt vector or interrupt vector range." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'dpd*' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_NUMBER, 0, "index", "Index into the page directory." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address which page directory entry to start dumping from. Range is applied to the page directory." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'dpda' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address of the page directory entry to start dumping from." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'dph*' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_GC_POINTER, 0, "address", "Where in the address space to start dumping and for how long (range). The default address/range will be used if omitted." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_NUMBER, DBGCVD_FLAGS_DEP_PREV, "cr3", "The CR3 value to use. The current CR3 of the context will be used if omitted." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_STRING, DBGCVD_FLAGS_DEP_PREV, "mode", "The paging mode: legacy, pse, pae, long, ept. Append '-np' for nested paging and '-nx' for no-execute. The current mode will be used if omitted." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'dpt?' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address which page directory entry to start dumping from." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'dpta' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address of the page table entry to start dumping from." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'dt' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_NUMBER, 0, "tss", "TSS selector number." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_POINTER, 0, "tss:ign|addr", "TSS address. If the selector is a TSS selector, the offset will be ignored." }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'e?' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address where to write." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, ~0U, DBGCVAR_CAT_NUMBER, 0, "value", "Value to write." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'lm' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, ~0U, DBGCVAR_CAT_STRING, 0, "module", "Module name." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'ln' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, ~0U, DBGCVAR_CAT_POINTER, 0, "address", "Address of the symbol to look up." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, ~0U, DBGCVAR_CAT_SYMBOL, 0, "symbol", "Symbol to lookup." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'ls' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk { 0, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address where to start looking for source lines." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'm' argument. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, 1, DBGCVAR_CAT_POINTER, 0, "address", "Pointer to obtain info about." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'r' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_SYMBOL, 0, "register", "Register to show or set." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_NUMBER_NO_RANGE, DBGCVD_FLAGS_DEP_PREV, "value", "New register value." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 's' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_OPTION, 0, "-b", "Byte string." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_OPTION, 0, "-w", "Word string." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_OPTION, 0, "-d", "DWord string." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_OPTION, 0, "-q", "QWord string." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_OPTION, 0, "-a", "ASCII string." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_OPTION, 0, "-u", "Unicode string." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_OPTION_NUMBER, 0, "-n <Hits>", "Maximum number of hits." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_GC_POINTER, 0, "range", "Register to show or set." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, ~0U, DBGCVAR_CAT_ANY, 0, "pattern", "Pattern to search for." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 's?' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, 1, DBGCVAR_CAT_GC_POINTER, 0, "range", "Register to show or set." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 1, ~0U, DBGCVAR_CAT_ANY, 0, "pattern", "Pattern to search for." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** 'u' arguments. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { 0, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address where to start disassembling." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** Command descriptors for the CodeView / WinDbg emulation.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * The emulation isn't attempting to be identical, only somewhat similar.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /* pszCmd, cArgsMin, cArgsMax, paArgDescs, cArgDescs, fFlags, pfnHandler pszSyntax, ....pszDescription */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "ba", 3, 6, &g_aArgBrkAcc[0], RT_ELEMENTS(g_aArgBrkAcc), 0, dbgcCmdBrkAccess, "<access> <size> <address> [passes [max passes]] [cmds]",
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk "Sets a data access breakpoint." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "bc", 1, ~0U, &g_aArgBrks[0], RT_ELEMENTS(g_aArgBrks), 0, dbgcCmdBrkClear, "all | <bp#> [bp# []]", "Deletes a set of breakpoints." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "bd", 1, ~0U, &g_aArgBrks[0], RT_ELEMENTS(g_aArgBrks), 0, dbgcCmdBrkDisable, "all | <bp#> [bp# []]", "Disables a set of breakpoints." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "be", 1, ~0U, &g_aArgBrks[0], RT_ELEMENTS(g_aArgBrks), 0, dbgcCmdBrkEnable, "all | <bp#> [bp# []]", "Enables a set of breakpoints." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "bl", 0, 0, NULL, 0, 0, dbgcCmdBrkList, "", "Lists all the breakpoints." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "bp", 1, 4, &g_aArgBrkSet[0], RT_ELEMENTS(g_aArgBrkSet), 0, dbgcCmdBrkSet, "<address> [passes [max passes]] [cmds]",
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk "Sets a breakpoint (int 3)." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "br", 1, 4, &g_aArgBrkREM[0], RT_ELEMENTS(g_aArgBrkREM), 0, dbgcCmdBrkREM, "<address> [passes [max passes]] [cmds]",
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk "Sets a recompiler specific breakpoint." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "d", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory using last element size." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "da", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory as ascii string." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "db", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory in bytes." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dd", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory in double words." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "da", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory as ascii string." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dg", 0, ~0U, &g_aArgDumpDT[0], RT_ELEMENTS(g_aArgDumpDT), 0, dbgcCmdDumpDT, "[sel [..]]", "Dump the global descriptor table (GDT)." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dga", 0, ~0U, &g_aArgDumpDT[0], RT_ELEMENTS(g_aArgDumpDT), 0, dbgcCmdDumpDT, "[sel [..]]", "Dump the global descriptor table (GDT) including not-present entries." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "di", 0, ~0U, &g_aArgDumpIDT[0], RT_ELEMENTS(g_aArgDumpIDT), 0, dbgcCmdDumpIDT, "[int [..]]", "Dump the interrupt descriptor table (IDT)." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dia", 0, ~0U, &g_aArgDumpIDT[0], RT_ELEMENTS(g_aArgDumpIDT), 0, dbgcCmdDumpIDT, "[int [..]]", "Dump the interrupt descriptor table (IDT) including not-present entries." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dl", 0, ~0U, &g_aArgDumpDT[0], RT_ELEMENTS(g_aArgDumpDT), 0, dbgcCmdDumpDT, "[sel [..]]", "Dump the local descriptor table (LDT)." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dla", 0, ~0U, &g_aArgDumpDT[0], RT_ELEMENTS(g_aArgDumpDT), 0, dbgcCmdDumpDT, "[sel [..]]", "Dump the local descriptor table (LDT) including not-present entries." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dpd", 0, 1, &g_aArgDumpPD[0], RT_ELEMENTS(g_aArgDumpPD), 0, dbgcCmdDumpPageDir, "[addr|index]", "Dumps page directory entries of the default context." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dpda", 0, 1, &g_aArgDumpPDAddr[0],RT_ELEMENTS(g_aArgDumpPDAddr), 0, dbgcCmdDumpPageDir, "[addr]", "Dumps memory at given address as a page directory." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dpdb", 0, 1, &g_aArgDumpPD[0], RT_ELEMENTS(g_aArgDumpPD), 0, dbgcCmdDumpPageDirBoth, "[addr|index]", "Dumps page directory entries of the guest and the hypervisor. " },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dpdg", 0, 1, &g_aArgDumpPD[0], RT_ELEMENTS(g_aArgDumpPD), 0, dbgcCmdDumpPageDir, "[addr|index]", "Dumps page directory entries of the guest." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dpdh", 0, 1, &g_aArgDumpPD[0], RT_ELEMENTS(g_aArgDumpPD), 0, dbgcCmdDumpPageDir, "[addr|index]", "Dumps page directory entries of the hypervisor. " },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dph", 0, 3, &g_aArgDumpPH[0], RT_ELEMENTS(g_aArgDumpPH), 0, dbgcCmdDumpPageHierarchy, "[addr [cr3 [mode]]", "Dumps the paging hierarchy at for specfied address range. Default context." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dphg", 0, 3, &g_aArgDumpPH[0], RT_ELEMENTS(g_aArgDumpPH), 0, dbgcCmdDumpPageHierarchy, "[addr [cr3 [mode]]", "Dumps the paging hierarchy at for specfied address range. Guest context." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dphh", 0, 3, &g_aArgDumpPH[0], RT_ELEMENTS(g_aArgDumpPH), 0, dbgcCmdDumpPageHierarchy, "[addr [cr3 [mode]]", "Dumps the paging hierarchy at for specfied address range. Hypervisor context." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dpt", 1, 1, &g_aArgDumpPT[0], RT_ELEMENTS(g_aArgDumpPT), 0, dbgcCmdDumpPageTable,"<addr>", "Dumps page table entries of the default context." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dpta", 1, 1, &g_aArgDumpPTAddr[0],RT_ELEMENTS(g_aArgDumpPTAddr), 0, dbgcCmdDumpPageTable,"<addr>", "Dumps memory at given address as a page table." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dptb", 1, 1, &g_aArgDumpPT[0], RT_ELEMENTS(g_aArgDumpPT), 0, dbgcCmdDumpPageTableBoth,"<addr>", "Dumps page table entries of the guest and the hypervisor." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dptg", 1, 1, &g_aArgDumpPT[0], RT_ELEMENTS(g_aArgDumpPT), 0, dbgcCmdDumpPageTable,"<addr>", "Dumps page table entries of the guest." },
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk { "dpth", 1, 1, &g_aArgDumpPT[0], RT_ELEMENTS(g_aArgDumpPT), 0, dbgcCmdDumpPageTable,"<addr>", "Dumps page table entries of the hypervisor." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dq", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory in quad words." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dt", 0, 1, &g_aArgDumpTSS[0], RT_ELEMENTS(g_aArgDumpTSS), 0, dbgcCmdDumpTSS, "[tss|tss:ign|addr]", "Dump the task state segment (TSS)." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dt16", 0, 1, &g_aArgDumpTSS[0], RT_ELEMENTS(g_aArgDumpTSS), 0, dbgcCmdDumpTSS, "[tss|tss:ign|addr]", "Dump the 16-bit task state segment (TSS)." },
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk { "dt32", 0, 1, &g_aArgDumpTSS[0], RT_ELEMENTS(g_aArgDumpTSS), 0, dbgcCmdDumpTSS, "[tss|tss:ign|addr]", "Dump the 32-bit task state segment (TSS)." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dt64", 0, 1, &g_aArgDumpTSS[0], RT_ELEMENTS(g_aArgDumpTSS), 0, dbgcCmdDumpTSS, "[tss|tss:ign|addr]", "Dump the 64-bit task state segment (TSS)." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "dw", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory in words." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /** @todo add 'e', 'ea str', 'eza str', 'eu str' and 'ezu str'. See also
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * dbgcCmdSearchMem and its dbgcVarsToBytes usage. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "eb", 2, 2, &g_aArgEditMem[0], RT_ELEMENTS(g_aArgEditMem), 0, dbgcCmdEditMem, "<addr> <value>", "Write a 1-byte value to memory." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "ew", 2, 2, &g_aArgEditMem[0], RT_ELEMENTS(g_aArgEditMem), 0, dbgcCmdEditMem, "<addr> <value>", "Write a 2-byte value to memory." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "ed", 2, 2, &g_aArgEditMem[0], RT_ELEMENTS(g_aArgEditMem), 0, dbgcCmdEditMem, "<addr> <value>", "Write a 4-byte value to memory." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "eq", 2, 2, &g_aArgEditMem[0], RT_ELEMENTS(g_aArgEditMem), 0, dbgcCmdEditMem, "<addr> <value>", "Write a 8-byte value to memory." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "g", 0, 0, NULL, 0, 0, dbgcCmdGo, "", "Continue execution." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "k", 0, 0, NULL, 0, 0, dbgcCmdStack, "", "Callstack." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "kg", 0, 0, NULL, 0, 0, dbgcCmdStack, "", "Callstack - guest." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "kh", 0, 0, NULL, 0, 0, dbgcCmdStack, "", "Callstack - hypervisor." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "lm", 0, ~0U, &g_aArgListMods[0], RT_ELEMENTS(g_aArgListMods), 0, dbgcCmdListModules, "[module [..]]", "List modules." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "lmv", 0, ~0U, &g_aArgListMods[0], RT_ELEMENTS(g_aArgListMods), 0, dbgcCmdListModules, "[module [..]]", "List modules, verbose." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "lmo", 0, ~0U, &g_aArgListMods[0], RT_ELEMENTS(g_aArgListMods), 0, dbgcCmdListModules, "[module [..]]", "List modules and their segments." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "lmov", 0, ~0U, &g_aArgListMods[0], RT_ELEMENTS(g_aArgListMods), 0, dbgcCmdListModules, "[module [..]]", "List modules and their segments, verbose." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "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." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "ls", 0, 1, &g_aArgListSource[0],RT_ELEMENTS(g_aArgListSource), 0, dbgcCmdListSource, "[addr]", "Source." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "m", 1, 1, &g_aArgMemoryInfo[0],RT_ELEMENTS(g_aArgMemoryInfo), 0, dbgcCmdMemoryInfo, "<addr>", "Display information about that piece of memory." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "r", 0, 2, &g_aArgReg[0], RT_ELEMENTS(g_aArgReg), 0, dbgcCmdReg, "[reg [newval]]", "Show or set register(s) - active reg set." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "rg", 0, 2, &g_aArgReg[0], RT_ELEMENTS(g_aArgReg), 0, dbgcCmdRegGuest, "[reg [newval]]", "Show or set register(s) - guest reg set." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "rg32", 0, 0, NULL, 0, 0, dbgcCmdRegGuest, "", "Show 32-bit guest registers." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "rg64", 0, 0, NULL, 0, 0, dbgcCmdRegGuest, "", "Show 64-bit guest registers." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "rh", 0, 2, &g_aArgReg[0], RT_ELEMENTS(g_aArgReg), 0, dbgcCmdRegHyper, "[reg [newval]]", "Show or set register(s) - hypervisor reg set." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "rt", 0, 0, NULL, 0, 0, dbgcCmdRegTerse, "", "Toggles terse / verbose register info." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "s", 0, ~0U, &g_aArgSearchMem[0], RT_ELEMENTS(g_aArgSearchMem), 0, dbgcCmdSearchMem, "[options] <range> <pattern>", "Continue last search." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "sa", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for an ascii string." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "sb", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for one or more bytes." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "sd", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for one or more double words." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "sq", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for one or more quad words." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "su", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for an unicode string." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "sw", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for one or more words." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "t", 0, 0, NULL, 0, 0, dbgcCmdTrace, "", "Instruction trace (step into)." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "u", 0, 1, &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble), 0, dbgcCmdUnassemble, "[addr]", "Unassemble." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "u64", 0, 1, &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble), 0, dbgcCmdUnassemble, "[addr]", "Unassemble 64-bit code." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "u32", 0, 1, &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble), 0, dbgcCmdUnassemble, "[addr]", "Unassemble 32-bit code." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "u16", 0, 1, &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble), 0, dbgcCmdUnassemble, "[addr]", "Unassemble 16-bit code." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk { "uv86", 0, 1, &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble), 0, dbgcCmdUnassemble, "[addr]", "Unassemble 16-bit code with v8086/real mode addressing." },
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** The number of commands in the CodeView/WinDbg emulation. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkconst uint32_t g_cCmdsCodeView = RT_ELEMENTS(g_aCmdsCodeView);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @interface_method_impl{FNDBCCMD, The 'go' command.}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(int) dbgcCmdGo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Check if the VM is halted or not before trying to resume it.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpFail(pCmdHlp, pCmd, "The VM is already running");
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3Resume");
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @interface_method_impl{FNDBCCMD, The 'ba' command.}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(int) dbgcCmdBrkAccess(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Interpret access type.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid access type '%s' for '%s'. Valid types are 'e', 'r', 'w' and 'i'",
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Validate size.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (fType == X86_DR7_RW_EO && paArgs[1].u.u64Number != 1)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid access size %RX64 for '%s'. 'x' access type requires size 1!",
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /*case 8: - later*/
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid access size %RX64 for '%s'. 1, 2 or 4!",
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Convert the pointer to a DBGF address.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int rc = DBGCCmdHlpVarToDbgfAddr(pCmdHlp, &paArgs[2], &Address);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGCCmdHlpVarToDbgfAddr(,%DV,)", &paArgs[2]);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Pick out the optional arguments.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_STRING)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Try set the breakpoint.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGFR3BpSetReg(pUVM, &Address, iHitTrigger, iHitDisable, fType, cb, &iBp);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpPrintf(pCmdHlp, "Set access breakpoint %u at %RGv\n", iBp, Address.FlatPtr);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpPrintf(pCmdHlp, "Updated access breakpoint %u at %RGv\n", iBp, Address.FlatPtr);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "Failed to set access breakpoint at %RGv", Address.FlatPtr);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @interface_method_impl{FNDBCCMD, The 'bc' command.}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(int) dbgcCmdBrkClear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Enumerate the arguments.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (unsigned iArg = 0; iArg < cArgs && RT_SUCCESS(rc); iArg++)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk uint32_t iBp = (uint32_t)paArgs[iArg].u.u64Number;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc2, "DBGFR3BpClear(,%#x)", iBp);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (RT_SUCCESS(rc2) || rc2 == VERR_DBGF_BP_NOT_FOUND)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Breakpoint id %RX64 is too large", paArgs[iArg].u.u64Number);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk else if (!strcmp(paArgs[iArg].u.pszString, "all"))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc2, "DBGFR3BpClear(,%#x)", iBp);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (RT_SUCCESS(rc2) || rc2 == VERR_DBGF_BP_NOT_FOUND)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid argument '%s'", paArgs[iArg].u.pszString);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @interface_method_impl{FNDBCCMD, The 'bd' command.}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(int) dbgcCmdBrkDisable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Enumerate the arguments.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (unsigned iArg = 0; iArg < cArgs && RT_SUCCESS(rc); iArg++)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk uint32_t iBp = (uint32_t)paArgs[iArg].u.u64Number;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3BpDisable failed for breakpoint %#x", iBp);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Breakpoint id %RX64 is too large", paArgs[iArg].u.u64Number);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk else if (!strcmp(paArgs[iArg].u.pszString, "all"))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (PDBGCBP pBp = pDbgc->pFirstBp; pBp; pBp = pBp->pNext)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc2, "DBGFR3BpDisable failed for breakpoint %#x", pBp->iBp);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid argument '%s'", paArgs[iArg].u.pszString);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @interface_method_impl{FNDBCCMD, The 'be' command.}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(int) dbgcCmdBrkEnable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Enumerate the arguments.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (unsigned iArg = 0; iArg < cArgs && RT_SUCCESS(rc); iArg++)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk uint32_t iBp = (uint32_t)paArgs[iArg].u.u64Number;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3BpEnable failed for breakpoint %#x", iBp);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Breakpoint id %RX64 is too large", paArgs[iArg].u.u64Number);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk else if (!strcmp(paArgs[iArg].u.pszString, "all"))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for (PDBGCBP pBp = pDbgc->pFirstBp; pBp; pBp = pBp->pNext)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc2, "DBGFR3BpEnable failed for breakpoint %#x", pBp->iBp);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid argument '%s'", paArgs[iArg].u.pszString);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Breakpoint enumeration callback function.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @returns VBox status code. Any failure will stop the enumeration.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pUVM The user mode VM handle.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pvUser The user argument.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @param pBp Pointer to the breakpoint information. (readonly)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(int) dbgcEnumBreakpointsCallback(PUVM pUVM, void *pvUser, PCDBGFBP pBp)
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk * BP type and size.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%#4x %c %d %c %RGv %04RX64 (%04RX64 to ",
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pBp->iBp, pBp->fEnabled ? 'e' : 'd', (int)cb, chType,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%04RX64)", pBp->iHitDisable);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Try resolve the address.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int rc = DBGFR3AsSymbolByAddr(pUVM, pDbgc->hDbgAs, DBGFR3AddrFromFlat(pDbgc->pUVM, &Addr, pBp->GCPtr), &off, &Sym, NULL);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%s", Sym.szName);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk else if (off > 0)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%s+%RGv", Sym.szName, off);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%s+%RGv", Sym.szName, -off);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * The commands.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "\n cmds: '%s'\n", pDbgcBp->szCmd);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk DBGCCmdHlpPrintf(&pDbgc->CmdHlp, " [unknown bp]\n");
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @interface_method_impl{FNDBCCMD, The 'bl' command.}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(int) dbgcCmdBrkList(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, -1, cArgs == 0);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Enumerate the breakpoints.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int rc = DBGFR3BpEnum(pUVM, dbgcEnumBreakpointsCallback, pDbgc);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3BpEnum");
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @interface_method_impl{FNDBCCMD, The 'bp' command.}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(int) dbgcCmdBrkSet(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Convert the pointer to a DBGF address.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int rc = DBGCCmdHlpVarToDbgfAddr(pCmdHlp, &paArgs[0], &Address);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGCCmdHlpVarToDbgfAddr(,'%DV',)", &paArgs[0]);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Pick out the optional arguments.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_NUMBER)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (iArg < cArgs && paArgs[iArg].enmType == DBGCVAR_TYPE_STRING)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Try set the breakpoint.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = DBGFR3BpSet(pUVM, &Address, iHitTrigger, iHitDisable, &iBp);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpPrintf(pCmdHlp, "Set breakpoint %u at %RGv\n", iBp, Address.FlatPtr);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpPrintf(pCmdHlp, "Updated breakpoint %u at %RGv\n", iBp, Address.FlatPtr);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "Failed to set breakpoint at %RGv", Address.FlatPtr);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * @interface_method_impl{FNDBCCMD, The 'br' command.}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic DECLCALLBACK(int) dbgcCmdBrkREM(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Convert the pointer to a DBGF address.
iArg++;
iArg++;
iArg++;
return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "Failed to set REM breakpoint at %RGv", Address.FlatPtr);
static DECLCALLBACK(int) dbgcCmdUnassemble(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, cArgs == 0 || DBGCVAR_ISPOINTER(paArgs[0].enmType));
default: AssertFailed();
if (!cArgs)
pDbgc->SourcePos.u.GCFar.off = pDbgc->fRegCtxGuest ? CPUMGetGuestEIP(pVCpu) : CPUMGetHyperEIP(pVCpu);
case DBGCVAR_RANGE_NONE:
case DBGCVAR_RANGE_ELEMENTS:
case DBGCVAR_RANGE_BYTES:
int rc;
case DBGCVAR_TYPE_GC_FLAT:
case DBGCVAR_TYPE_GC_FAR:
case DBGCVAR_TYPE_GC_PHYS:
case DBGCVAR_TYPE_HC_FLAT:
case DBGCVAR_TYPE_HC_PHYS:
default: AssertFailed(); break;
return rc;
rc = DBGFR3DisasInstrEx(pUVM, pDbgc->idCpu, pDbgc->DisasmPos.u.GCFar.sel, pDbgc->DisasmPos.u.GCFar.off, fFlags,
return rc;
return rc;
if (cTries-- > 0)
iRangeLeft--;
return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGCCmdHlpEval(,,'(%Dv) + %x')", &pDbgc->DisasmPos, cbInstr);
if (iRangeLeft <= 0)
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdListSource(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
if (!cArgs)
pDbgc->SourcePos.u.GCFar.off = pDbgc->fRegCtxGuest ? CPUMGetGuestEIP(pVCpu) : CPUMGetHyperEIP(pVCpu);
case DBGCVAR_TYPE_GC_FLAT:
case DBGCVAR_TYPE_GC_PHYS:
case DBGCVAR_TYPE_GC_FAR:
case DBGCVAR_TYPE_HC_FLAT:
case DBGCVAR_TYPE_HC_PHYS:
default: AssertFailed(); break;
case DBGCVAR_RANGE_NONE:
case DBGCVAR_RANGE_ELEMENTS:
case DBGCVAR_RANGE_BYTES:
return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: Unknown range type %d.\n", pDbgc->SourcePos.enmRangeType);
return VINF_SUCCESS;
unsigned cLines = 0;
fFirst = true;
if (fFirst)
return rc;
if (phFile)
cBefore = 0;
while (cLeft > 0)
cLeft--;
if (!cLeft)
while (cch > 0 && (szLine[cch - 1] == '\r' || szLine[cch - 1] == '\n' || RT_C_IS_SPACE(szLine[cch - 1])) )
if (cBefore-- <= 0)
cLines++;
return rc;
fFirst = false;
return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Warning: couldn't open source file '%s'\n", Line.szFilename);
if (iRangeLeft <= 0)
static DECLCALLBACK(int) dbgcCmdReg(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
static DECLCALLBACK(int) dbgcCmdRegCommon(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs,
const char *pszPrefix)
pszReg++;
if (*pszPrefix)
pszReg++;
return rc;
static DECLCALLBACK(int) dbgcCmdRegGuest(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
if (cArgs == 0)
int rc;
if (f64BitMode)
"cs=%04VR{cs} ds=%04VR{ds} es=%04VR{es} fs=%04VR{fs} gs=%04VR{gs} ss=%04VR{ss} rflags=%08VR{rflags}\n");
"cs=%04VR{cs} ds=%04VR{ds} es=%04VR{es} fs=%04VR{fs} gs=%04VR{gs} ss=%04VR{ss} eflags=%08VR{eflags}\n");
if (f64BitMode)
"gdtr=%016VR{gdtr_base}:%04VR{gdtr_lim} idtr=%016VR{idtr_base}:%04VR{idtr_lim} rflags=%08VR{rflags}\n"
"cs={%04VR{cs} base=%08VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} dr0=%08VR{dr0} dr1=%08VR{dr1}\n"
"ds={%04VR{ds} base=%08VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} dr2=%08VR{dr2} dr3=%08VR{dr3}\n"
"es={%04VR{es} base=%08VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} dr6=%08VR{dr6} dr7=%08VR{dr7}\n"
"fs={%04VR{fs} base=%08VR{fs_base} limit=%08VR{fs_lim} flags=%04VR{fs_attr}} cr0=%08VR{cr0} cr2=%08VR{cr2}\n"
"gs={%04VR{gs} base=%08VR{gs_base} limit=%08VR{gs_lim} flags=%04VR{gs_attr}} cr3=%08VR{cr3} cr4=%08VR{cr4}\n"
"gdtr=%08VR{gdtr_base}:%04VR{gdtr_lim} idtr=%08VR{idtr_base}:%04VR{idtr_lim} eflags=%08VR{eflags}\n"
static DECLCALLBACK(int) dbgcCmdRegHyper(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
if (cArgs == 0)
int rc;
rc = DBGFR3RegPrintf(pUVM, pDbgc->idCpu | DBGFREG_HYPER_VMCPUID, szDisAndRegs, sizeof(szDisAndRegs),
".cs=%04VR{cs} .ds=%04VR{ds} .es=%04VR{es} .fs=%04VR{fs} .gs=%04VR{gs} .ss=%04VR{ss} .eflags=%08VR{eflags}\n");
rc = DBGFR3RegPrintf(pUVM, pDbgc->idCpu | DBGFREG_HYPER_VMCPUID, szDisAndRegs, sizeof(szDisAndRegs),
".cs={%04VR{cs} base=%08VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} .dr0=%08VR{dr0} .dr1=%08VR{dr1}\n"
".ds={%04VR{ds} base=%08VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} .dr2=%08VR{dr2} .dr3=%08VR{dr3}\n"
".es={%04VR{es} base=%08VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} .dr6=%08VR{dr6} .dr6=%08VR{dr6}\n"
".gdtr=%08VR{gdtr_base}:%04VR{gdtr_lim} .idtr=%08VR{idtr_base}:%04VR{idtr_lim} .eflags=%08VR{eflags}\n"
static DECLCALLBACK(int) dbgcCmdRegTerse(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
return pCmdHlp->pfnPrintf(pCmdHlp, NULL, pDbgc->fRegTerse ? "info: Terse register info.\n" : "info: Verbose register info.\n");
static DECLCALLBACK(int) dbgcCmdTrace(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "When trying to single step VM %p\n", pDbgc->pVM);
return rc;
static DECLCALLBACK(int) dbgcCmdStack(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
int rc;
rc = DBGFR3StackWalkBegin(pUVM, pDbgc->idCpu, fGuest ? DBGFCODETYPE_GUEST : DBGFCODETYPE_HYPER, &pFirstFrame);
uint32_t const fCurBitFlags = pFrame->fFlags & (DBGFSTACKFRAME_FLAGS_16BIT | DBGFSTACKFRAME_FLAGS_32BIT | DBGFSTACKFRAME_FLAGS_64BIT);
pCmdHlp->pfnPrintf(pCmdHlp, NULL, "SS:BP Ret SS:BP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP / Symbol [line]\n");
rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04RX16:%04RX16 %04RX16:%04RX16 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",
pCmdHlp->pfnPrintf(pCmdHlp, NULL, "EBP Ret EBP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP / Symbol [line]\n");
rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%08RX32 %08RX32 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",
RTGCINTPTR offDisp = pFrame->AddrPC.FlatPtr - pFrame->pSymPC->Value; /** @todo this isn't 100% correct for segmented stuff. */
if (offDisp > 0)
else if (offDisp < 0)
rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, " [%s @ 0i%d]", pFrame->pLinePC->szFilename, pFrame->pLinePC->uLineNo);
return rc;
static int dbgcCmdDumpDTWorker64(PDBGCCMDHLP pCmdHlp, PCX86DESC64 pDesc, unsigned iEntry, bool fHyper, bool *pfDblEntry)
int rc;
static const char * const s_apszTypes[] =
rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %s Bas=%08x Lim=%08x DPL=%d %s %s %s %s AVL=%d L=%d%s\n",
static const char * const s_apszTypes[] =
case X86_SEL_TYPE_SYS_LDT:
rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %s Bas=%016RX64 Lim=%08x DPL=%d %s %s %s %sAVL=%d R=%d%s\n",
pszHyper);
if (pfDblEntry)
*pfDblEntry = true;
if (pfDblEntry)
*pfDblEntry = true;
if (pfDblEntry)
*pfDblEntry = true;
return VINF_SUCCESS;
return VINF_SUCCESS;
static int dbgcCmdDumpDTWorker32(PDBGCCMDHLP pCmdHlp, PCX86DESC pDesc, unsigned iEntry, bool fHyper)
int rc;
static const char * const s_apszTypes[] =
rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %s Bas=%08x Lim=%08x DPL=%d %s %s %s %s AVL=%d L=%d%s\n",
static const char * const s_apszTypes[] =
case X86_SEL_TYPE_SYS_LDT:
rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%04x %s Bas=%08x Lim=%08x DPL=%d %s %s %s %s AVL=%d R=%d%s\n",
pszHyper);
return VINF_SUCCESS;
return rc;
static DECLCALLBACK(int) dbgcCmdDumpDT(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
if (!cArgs)
for (unsigned i = 0; i < cArgs; i++)
DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, i, paArgs[i].enmType == DBGCVAR_TYPE_NUMBER || DBGCVAR_ISPOINTER(paArgs[i].enmType));
case DBGCVAR_TYPE_NUMBER:
while ( cSels-- > 0
int rc = DBGFR3SelQueryInfo(pUVM, pDbgc->idCpu, Sel | SelTable, DBGFSELQI_FLAGS_DT_GUEST, &SelInfo);
else if ( fAll
|| fSingle
rc = dbgcCmdDumpDTWorker32(pCmdHlp, &SelInfo.u.Raw, Sel, !!(SelInfo.fFlags & DBGFSELINFO_FLAGS_HYPER));
bool fDblSkip = false;
rc = dbgcCmdDumpDTWorker64(pCmdHlp, &SelInfo.u.Raw64, Sel, !!(SelInfo.fFlags & DBGFSELINFO_FLAGS_HYPER), &fDblSkip);
if (fDblSkip)
if (!fAll)
return rc;
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdDumpIDT(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
unsigned cbEntry;
switch (enmMode)
if (!cArgs)
for (unsigned i = 0; i < cArgs; i++)
while ( cInts-- > 0
return VINF_SUCCESS;
switch (enmMode)
case CPUMMODE_REAL:
case CPUMMODE_PROTECTED:
case CPUMMODE_LONG:
return rc;
iInt++;
pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: %llx is out of bounds (max 256)\n", paArgs[i].u.u64Number);
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdDumpMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
unsigned cbElement;
bool fAscii = false;
fAscii = true;
if (!cbElement)
if (!cArgs)
case DBGCVAR_RANGE_NONE:
case DBGCVAR_RANGE_ELEMENTS:
return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Too many elements requested. Max is 2048 elements.\n");
case DBGCVAR_RANGE_BYTES:
return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: Unknown range type %d.\n", pDbgc->DumpPos.enmRangeType);
if (!fAscii)
switch (cbElement)
case 8: pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%s%016llx", pszSpace, *(uint64_t *)&achBuffer[i]); break;
while (i++ < sizeof(achBuffer))
if (!u8Prev)
for (i = 0; i < cb; i++)
else if (!u8)
if (cbLeft <= 0)
return VINF_SUCCESS;
static RTGCPHYS dbgcGetGuestPageMode(PDBGC pDbgc, bool *pfPAE, bool *pfLME, bool *pfPSE, bool *pfPGE, bool *pfNXE)
*pfPSE = true;
*pfPAE = true;
*pfPAE = false;
static RTHCPHYS dbgcGetShadowPageMode(PDBGC pDbgc, bool *pfPAE, bool *pfLME, bool *pfPSE, bool *pfPGE, bool *pfNXE)
*pfPSE = true;
*pfPGE = false;
case PGMMODE_32_BIT:
case PGMMODE_PAE:
*pfPAE = true;
case PGMMODE_PAE_NX:
*pfLME = false;
case PGMMODE_AMD64:
*pfNXE = false;
case PGMMODE_AMD64_NX:
static DECLCALLBACK(int) dbgcCmdDumpPageDir(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
if (!cArgs)
return DBGCCmdHlpPrintf(pCmdHlp, "Default argument for 'dpda' hasn't been fully implemented yet. Try with an address or use one of the other commands.\n");
if (fGuest)
if (fPAE)
int rc;
if (fPAE)
if (fGuest)
if (fLME)
VarCur.u.u64Number += (((uint64_t)VarGCPtr.u.GCFlat >> X86_PML4_SHIFT) & X86_PML4_MASK) * sizeof(X86PML4E);
return DBGCCmdHlpPrintf(pCmdHlp, "Page directory pointer table is not present for %Dv.\n", &VarGCPtr);
if (fPAE)
Pde.u = 0;
if (iEntry != ~0U)
iEntry++;
Pde.u,
Pde.u,
return rc;
if (iEntry != ~0U)
} while (cEntries-- > 0);
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdDumpPageDirBoth(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
return rc1;
return rc2;
static DECLCALLBACK(int) dbgcCmdDumpPageHierarchy(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
AssertFailed();
else if (!cbRange)
if ((fFlags & (DBGFPGDMP_FLAGS_GUEST | DBGFPGDMP_FLAGS_SHADOW)) == (DBGFPGDMP_FLAGS_GUEST | DBGFPGDMP_FLAGS_SHADOW))
return DBGCCmdHlpFail(pCmdHlp, pCmd, "No CR3 or mode arguments when dumping both context, please.");
static const struct MODETOFLAGS
const char *pszName;
} s_aModeToFlags[] =
{ "pae-nx-np", DBGFPGDMP_FLAGS_PSE | DBGFPGDMP_FLAGS_PAE | DBGFPGDMP_FLAGS_NXE | DBGFPGDMP_FLAGS_NP },
{ "long-np", DBGFPGDMP_FLAGS_PSE | DBGFPGDMP_FLAGS_PAE | DBGFPGDMP_FLAGS_LME | DBGFPGDMP_FLAGS_NP },
{ "long-nx", DBGFPGDMP_FLAGS_PSE | DBGFPGDMP_FLAGS_PAE | DBGFPGDMP_FLAGS_LME | DBGFPGDMP_FLAGS_NXE },
{ "long-nx-np", DBGFPGDMP_FLAGS_PSE | DBGFPGDMP_FLAGS_PAE | DBGFPGDMP_FLAGS_LME | DBGFPGDMP_FLAGS_NXE | DBGFPGDMP_FLAGS_NP }
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdDumpPageTable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
int rc;
if (fGuest)
if (fLME)
VarCur.u.u64Number += (((uint64_t)VarGCPtr.u.GCFlat >> X86_PML4_SHIFT) & X86_PML4_MASK) * sizeof(X86PML4E);
return DBGCCmdHlpPrintf(pCmdHlp, "Page directory pointer table is not present for %Dv.\n", &VarGCPtr);
if (fPAE)
Pte.u = 0;
if (iEntry != ~0U)
iEntry++;
Pte.u,
return rc;
if (iEntry != ~0U)
} while (cEntries-- > 0);
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdDumpPageTableBoth(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
return rc1;
return rc2;
static DECLCALLBACK(int) dbgcCmdDumpTSS(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
int rc;
* We can get a TSS selector (number), a far pointer using a TSS selector, or some kind of TSS pointer.
if (cArgs == 0)
rc = DBGFR3SelQueryInfo(pUVM, pDbgc->idCpu, VarTssAddr.u.GCFar.sel, DBGFSELQI_FLAGS_DT_GUEST, &SelInfo);
return DBGCCmdHlpFail(pCmdHlp, pCmd, "%04x is not a TSS selector. (!sys)\n", VarTssAddr.u.GCFar.sel);
switch (enmTssType)
case kTss16:
case kTss32:
case kTss64:
uint32_t cbTss = VarTssAddr.enmRangeType == DBGCVAR_RANGE_BYTES ? (uint32_t)VarTssAddr.u64Range : 0;
if (cbTss == 0)
return DBGCCmdHlpFail(pCmdHlp, pCmd, "Minimum TSS size is %u bytes, you specified %llu (%llx) bytes.\n",
return DBGCCmdHlpFail(pCmdHlp, pCmd, "Failed to read essential parts of the TSS (read %zu, min %zu).\n",
switch (enmTssType)
case kTss16:
offIoBitmap = 0;
case kTss32:
case kTss64:
DBGCCmdHlpPrintf(pCmdHlp, "%02x-%02x %s\n", iStart, i - 1, fPrev ? "Protected mode" : "Redirected");
iStart = i;
DBGCCmdHlpPrintf(pCmdHlp, "Invalid interrupt redirection bitmap size: %u (%#x), expected 32 bytes.\n",
else if (offIoBitmap > 0)
cLine++;
iStart = i;
else if (offIoBitmap > 0)
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdMemoryInfo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
int dbgcVarsToBytes(PDBGCCMDHLP pCmdHlp, void *pvBuf, uint32_t *pcbBuf, size_t cbUnit, PCDBGCVAR paVars, unsigned cVars)
} u, uEnd;
case DBGCVAR_TYPE_GC_FAR:
case DBGCVAR_TYPE_GC_FLAT:
case DBGCVAR_TYPE_GC_PHYS:
case DBGCVAR_TYPE_HC_FLAT:
case DBGCVAR_TYPE_HC_PHYS:
case DBGCVAR_TYPE_NUMBER:
} while (u64);
} while (u64);
if (u64)
case DBGCVAR_TYPE_STRING:
case DBGCVAR_TYPE_SYMBOL:
return VERR_TOO_MUCH_DATA;
while (*psz)
psz++;
return VERR_TOO_MUCH_DATA;
if (cbReminder)
return VERR_INTERNAL_ERROR;
if (i != cVars)
return VERR_TOO_MUCH_DATA;
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdEditMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
unsigned iArg;
unsigned cbElement;
iArg++;
return VINF_SUCCESS;
static int dbgcCmdWorkerSearchMemDoIt(PDBGCCMDHLP pCmdHlp, PUVM pUVM, PDBGFADDRESS pAddress, RTGCUINTPTR cbRange,
cbRange = 0;
if (!pResult)
cbRange = 0;
return VERR_DBGC_COMMAND_FAILED;
if (!cbRange)
return dbgcCmdWorkerSearchMemDoIt(pCmdHlp, pUVM, &Address, cbRange, pDbgc->abSearch, pDbgc->cbSearch,
static int dbgcCmdWorkerSearchMem(PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR pAddress, uint64_t cMaxHits, char chType,
if (pResult)
switch (chType)
return VERR_DBGC_COMMAND_FAILED;
case DBGCVAR_RANGE_BYTES:
case DBGCVAR_RANGE_ELEMENTS:
return dbgcCmdWorkerSearchMemDoIt(pCmdHlp, pUVM, &Address, cbRange, abBytes, cbBytes, cbUnit, cMaxHits, pResult);
static DECLCALLBACK(int) dbgcCmdSearchMem(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
if (cArgs == 0)
static DECLCALLBACK(int) dbgcCmdSearchMemType(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, cArgs >= 2 && DBGCVAR_ISGCPOINTER(paArgs[0].enmType));
return dbgcCmdWorkerSearchMem(pCmdHlp, pUVM, &paArgs[0], 25, pCmd->pszCmd[1], paArgs + 1, cArgs - 1, NULL);
int rc;
rc = DBGFR3AsSymbolByAddr(pUVM, pDbgc->hDbgAs, DBGFR3AddrFromFlat(pDbgc->pUVM, &Addr, AddrVar.u.GCFlat), &offDisp, &Symbol, NULL);
if (!offDisp)
else if (offDisp > 0)
return rc;
static DECLCALLBACK(int) dbgcCmdListNear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
if (!cArgs)
/** @todo Fix the darn parser, it's resolving symbols specified as arguments before we get in here. */
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdListModules(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
if ( cArgs == 0
bool fFull = false;
&& ( !fFull
if (fMappings)
&& !fDeferred)
else if (!fDeferred)
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcFuncReadU8(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, uint32_t cArgs,
uint8_t b;
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcFuncReadU16(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, uint32_t cArgs,
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcFuncReadU32(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, uint32_t cArgs,
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcFuncReadU64(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, uint32_t cArgs,
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcFuncReadPtr(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, uint32_t cArgs,
static DECLCALLBACK(int) dbgcFuncHi(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, uint32_t cArgs,
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcFuncLow(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, uint32_t cArgs,
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcFuncNot(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, uint32_t cArgs,
{ "by", 1, 1, &g_aArgPointerWoRange[0], RT_ELEMENTS(g_aArgPointerWoRange), 0, dbgcFuncReadU8, "address", "Reads a byte at the given address." },
{ "dwo", 1, 1, &g_aArgPointerWoRange[0], RT_ELEMENTS(g_aArgPointerWoRange), 0, dbgcFuncReadU32, "address", "Reads a 32-bit value at the given address." },
{ "hi", 1, 1, &g_aArgPointerNumber[0], RT_ELEMENTS(g_aArgPointerNumber), 0, dbgcFuncHi, "value", "Returns the high 16-bit bits of a value." },
{ "low", 1, 1, &g_aArgPointerNumber[0], RT_ELEMENTS(g_aArgPointerNumber), 0, dbgcFuncLow, "value", "Returns the low 16-bit bits of a value." },
{ "not", 1, 1, &g_aArgPointerNumber[0], RT_ELEMENTS(g_aArgPointerNumber), 0, dbgcFuncNot, "address", "Boolean NOT." },
{ "poi", 1, 1, &g_aArgPointerWoRange[0], RT_ELEMENTS(g_aArgPointerWoRange), 0, dbgcFuncReadPtr, "address", "Reads a pointer sized (CS) value at the given address." },
{ "qwo", 1, 1, &g_aArgPointerWoRange[0], RT_ELEMENTS(g_aArgPointerWoRange), 0, dbgcFuncReadU64, "address", "Reads a 32-bit value at the given address." },
{ "wo", 1, 1, &g_aArgPointerWoRange[0], RT_ELEMENTS(g_aArgPointerWoRange), 0, dbgcFuncReadU16, "address", "Reads a 16-bit value at the given address." },