DBGCEmulateCodeView.cpp revision 0c3b158e1a6ce423f4499f472f3717050476897d
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * DBGC - Debugger Console, CodeView / WinDbg Emulation.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * Copyright (C) 2006-2013 Oracle Corporation
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * available from http://www.virtualbox.org. This file is free software;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * you can redistribute it and/or modify it under the terms of the GNU
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * General Public License (GPL) as published by the Free Software
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/*******************************************************************************
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync* Header Files *
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync*******************************************************************************/
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/*******************************************************************************
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync* Internal Functions *
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync*******************************************************************************/
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/*******************************************************************************
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync* Global Variables *
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync*******************************************************************************/
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync/** 'ba' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 1, 1, DBGCVAR_CAT_STRING, 0, "access", "The access type: x=execute, rw=read/write (alias r), w=write, i=not implemented." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 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." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 1, 1, DBGCVAR_CAT_GC_POINTER, 0, "address", "The address." },
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 0, 1, DBGCVAR_CAT_NUMBER, 0, "passes", "The number of passes before we trigger the breakpoint. (0 is default)" },
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 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)" },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, 1, DBGCVAR_CAT_STRING, 0, "cmds", "String of commands to be executed when the breakpoint is hit. Quote it!" },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'bc', 'bd', 'be' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, ~0U, DBGCVAR_CAT_NUMBER, 0, "#bp", "Breakpoint number." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, 1, DBGCVAR_CAT_STRING, 0, "all", "All breakpoints." },
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync/** 'bp' arguments. */
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 1, 1, DBGCVAR_CAT_GC_POINTER, 0, "address", "The address." },
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 0, 1, DBGCVAR_CAT_NUMBER, 0, "passes", "The number of passes before we trigger the breakpoint. (0 is default)" },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 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)" },
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 0, 1, DBGCVAR_CAT_STRING, 0, "cmds", "String of commands to be executed when the breakpoint is hit. Quote it!" },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'br' arguments. */
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 1, 1, DBGCVAR_CAT_GC_POINTER, 0, "address", "The address." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, 1, DBGCVAR_CAT_NUMBER, 0, "passes", "The number of passes before we trigger the breakpoint. (0 is default)" },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 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)" },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, 1, DBGCVAR_CAT_STRING, 0, "cmds", "String of commands to be executed when the breakpoint is hit. Quote it!" },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'd?' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address where to start dumping memory." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'dg', 'dga', 'dl', 'dla' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, ~0U, DBGCVAR_CAT_NUMBER, 0, "sel", "Selector or selector range." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, ~0U, DBGCVAR_CAT_POINTER, 0, "address", "Far address which selector should be dumped." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'di', 'dia' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, ~0U, DBGCVAR_CAT_NUMBER, 0, "int", "The interrupt vector or interrupt vector range." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'dpd*' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, 1, DBGCVAR_CAT_NUMBER, 0, "index", "Index into the page directory." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address which page directory entry to start dumping from. Range is applied to the page directory." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'dpda' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address of the page directory entry to start dumping from." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'dph*' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 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." },
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 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." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 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." },
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync/** 'dpt?' arguments. */
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 1, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address which page directory entry to start dumping from." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'dpta' arguments. */
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 1, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address of the page table entry to start dumping from." },
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync/** 'dt' arguments. */
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 0, 1, DBGCVAR_CAT_NUMBER, 0, "tss", "TSS selector number." },
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 0, 1, DBGCVAR_CAT_POINTER, 0, "tss:ign|addr", "TSS address. If the selector is a TSS selector, the offset will be ignored." }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'e?' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync { 1, 1, DBGCVAR_CAT_POINTER, 0, "address", "Address where to write." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 1, ~0U, DBGCVAR_CAT_NUMBER, 0, "value", "Value to write." },
87f68d052aecda193e89e8f41ec147606c7f4e0bvboxsync/** 'lm' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync { 0, ~0U, DBGCVAR_CAT_STRING, 0, "module", "Module name." },
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** 'ln' arguments. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
/* pszCmd, cArgsMin, cArgsMax, paArgDescs, cArgDescs, fFlags, pfnHandler pszSyntax, ....pszDescription */
{ "ba", 3, 6, &g_aArgBrkAcc[0], RT_ELEMENTS(g_aArgBrkAcc), 0, dbgcCmdBrkAccess, "<access> <size> <address> [passes [max passes]] [cmds]",
{ "bc", 1, ~0U, &g_aArgBrks[0], RT_ELEMENTS(g_aArgBrks), 0, dbgcCmdBrkClear, "all | <bp#> [bp# []]", "Deletes a set of breakpoints." },
{ "bd", 1, ~0U, &g_aArgBrks[0], RT_ELEMENTS(g_aArgBrks), 0, dbgcCmdBrkDisable, "all | <bp#> [bp# []]", "Disables a set of breakpoints." },
{ "be", 1, ~0U, &g_aArgBrks[0], RT_ELEMENTS(g_aArgBrks), 0, dbgcCmdBrkEnable, "all | <bp#> [bp# []]", "Enables a set of breakpoints." },
{ "bp", 1, 4, &g_aArgBrkSet[0], RT_ELEMENTS(g_aArgBrkSet), 0, dbgcCmdBrkSet, "<address> [passes [max passes]] [cmds]",
{ "br", 1, 4, &g_aArgBrkREM[0], RT_ELEMENTS(g_aArgBrkREM), 0, dbgcCmdBrkREM, "<address> [passes [max passes]] [cmds]",
{ "d", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory using last element size." },
{ "da", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory as ascii string." },
{ "db", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory in bytes." },
{ "dd", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory in double words." },
{ "da", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory as ascii string." },
{ "dg", 0, ~0U, &g_aArgDumpDT[0], RT_ELEMENTS(g_aArgDumpDT), 0, dbgcCmdDumpDT, "[sel [..]]", "Dump the global descriptor table (GDT)." },
{ "dga", 0, ~0U, &g_aArgDumpDT[0], RT_ELEMENTS(g_aArgDumpDT), 0, dbgcCmdDumpDT, "[sel [..]]", "Dump the global descriptor table (GDT) including not-present entries." },
{ "di", 0, ~0U, &g_aArgDumpIDT[0], RT_ELEMENTS(g_aArgDumpIDT), 0, dbgcCmdDumpIDT, "[int [..]]", "Dump the interrupt descriptor table (IDT)." },
{ "dia", 0, ~0U, &g_aArgDumpIDT[0], RT_ELEMENTS(g_aArgDumpIDT), 0, dbgcCmdDumpIDT, "[int [..]]", "Dump the interrupt descriptor table (IDT) including not-present entries." },
{ "dl", 0, ~0U, &g_aArgDumpDT[0], RT_ELEMENTS(g_aArgDumpDT), 0, dbgcCmdDumpDT, "[sel [..]]", "Dump the local descriptor table (LDT)." },
{ "dla", 0, ~0U, &g_aArgDumpDT[0], RT_ELEMENTS(g_aArgDumpDT), 0, dbgcCmdDumpDT, "[sel [..]]", "Dump the local descriptor table (LDT) including not-present entries." },
{ "dpd", 0, 1, &g_aArgDumpPD[0], RT_ELEMENTS(g_aArgDumpPD), 0, dbgcCmdDumpPageDir, "[addr|index]", "Dumps page directory entries of the default context." },
{ "dpda", 0, 1, &g_aArgDumpPDAddr[0],RT_ELEMENTS(g_aArgDumpPDAddr), 0, dbgcCmdDumpPageDir, "[addr]", "Dumps memory at given address as a page directory." },
{ "dpdb", 0, 1, &g_aArgDumpPD[0], RT_ELEMENTS(g_aArgDumpPD), 0, dbgcCmdDumpPageDirBoth, "[addr|index]", "Dumps page directory entries of the guest and the hypervisor. " },
{ "dpdg", 0, 1, &g_aArgDumpPD[0], RT_ELEMENTS(g_aArgDumpPD), 0, dbgcCmdDumpPageDir, "[addr|index]", "Dumps page directory entries of the guest." },
{ "dpdh", 0, 1, &g_aArgDumpPD[0], RT_ELEMENTS(g_aArgDumpPD), 0, dbgcCmdDumpPageDir, "[addr|index]", "Dumps page directory entries of the hypervisor. " },
{ "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." },
{ "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." },
{ "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." },
{ "dpt", 1, 1, &g_aArgDumpPT[0], RT_ELEMENTS(g_aArgDumpPT), 0, dbgcCmdDumpPageTable,"<addr>", "Dumps page table entries of the default context." },
{ "dpta", 1, 1, &g_aArgDumpPTAddr[0],RT_ELEMENTS(g_aArgDumpPTAddr), 0, dbgcCmdDumpPageTable,"<addr>", "Dumps memory at given address as a page table." },
{ "dptb", 1, 1, &g_aArgDumpPT[0], RT_ELEMENTS(g_aArgDumpPT), 0, dbgcCmdDumpPageTableBoth,"<addr>", "Dumps page table entries of the guest and the hypervisor." },
{ "dptg", 1, 1, &g_aArgDumpPT[0], RT_ELEMENTS(g_aArgDumpPT), 0, dbgcCmdDumpPageTable,"<addr>", "Dumps page table entries of the guest." },
{ "dpth", 1, 1, &g_aArgDumpPT[0], RT_ELEMENTS(g_aArgDumpPT), 0, dbgcCmdDumpPageTable,"<addr>", "Dumps page table entries of the hypervisor." },
{ "dq", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory in quad words." },
{ "dt", 0, 1, &g_aArgDumpTSS[0], RT_ELEMENTS(g_aArgDumpTSS), 0, dbgcCmdDumpTSS, "[tss|tss:ign|addr]", "Dump the task state segment (TSS)." },
{ "dt16", 0, 1, &g_aArgDumpTSS[0], RT_ELEMENTS(g_aArgDumpTSS), 0, dbgcCmdDumpTSS, "[tss|tss:ign|addr]", "Dump the 16-bit task state segment (TSS)." },
{ "dt32", 0, 1, &g_aArgDumpTSS[0], RT_ELEMENTS(g_aArgDumpTSS), 0, dbgcCmdDumpTSS, "[tss|tss:ign|addr]", "Dump the 32-bit task state segment (TSS)." },
{ "dt64", 0, 1, &g_aArgDumpTSS[0], RT_ELEMENTS(g_aArgDumpTSS), 0, dbgcCmdDumpTSS, "[tss|tss:ign|addr]", "Dump the 64-bit task state segment (TSS)." },
{ "dw", 0, 1, &g_aArgDumpMem[0], RT_ELEMENTS(g_aArgDumpMem), 0, dbgcCmdDumpMem, "[addr]", "Dump memory in words." },
{ "eb", 2, 2, &g_aArgEditMem[0], RT_ELEMENTS(g_aArgEditMem), 0, dbgcCmdEditMem, "<addr> <value>", "Write a 1-byte value to memory." },
{ "ew", 2, 2, &g_aArgEditMem[0], RT_ELEMENTS(g_aArgEditMem), 0, dbgcCmdEditMem, "<addr> <value>", "Write a 2-byte value to memory." },
{ "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." },
{ "lm", 0, ~0U, &g_aArgListMods[0], RT_ELEMENTS(g_aArgListMods), 0, dbgcCmdListModules, "[module [..]]", "List modules." },
{ "lmo", 0, ~0U, &g_aArgListMods[0], RT_ELEMENTS(g_aArgListMods), 0, dbgcCmdListModules, "[module [..]]", "List modules and their segments." },
{ "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." },
{ "r", 0, 2, &g_aArgReg[0], RT_ELEMENTS(g_aArgReg), 0, dbgcCmdReg, "[reg [newval]]", "Show or set register(s) - active reg set." },
{ "rg", 0, 2, &g_aArgReg[0], RT_ELEMENTS(g_aArgReg), 0, dbgcCmdRegGuest, "[reg [newval]]", "Show or set register(s) - guest reg set." },
{ "rh", 0, 2, &g_aArgReg[0], RT_ELEMENTS(g_aArgReg), 0, dbgcCmdRegHyper, "[reg [newval]]", "Show or set register(s) - hypervisor reg set." },
{ "s", 0, ~0U, &g_aArgSearchMem[0], RT_ELEMENTS(g_aArgSearchMem), 0, dbgcCmdSearchMem, "[options] <range> <pattern>", "Continue last search." },
{ "sa", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for an ascii string." },
{ "sb", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for one or more bytes." },
{ "sd", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for one or more double words." },
{ "sq", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for one or more quad words." },
{ "su", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for an unicode string." },
{ "sw", 2, ~0U, &g_aArgSearchMemType[0], RT_ELEMENTS(g_aArgSearchMemType),0, dbgcCmdSearchMemType, "<range> <pattern>", "Search memory for one or more words." },
{ "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." },
{ "u16", 0, 1, &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble), 0, dbgcCmdUnassemble, "[addr]", "Unassemble 16-bit code." },
{ "uv86", 0, 1, &g_aArgUnassemble[0],RT_ELEMENTS(g_aArgUnassemble), 0, dbgcCmdUnassemble, "[addr]", "Unassemble 16-bit code with v8086/real mode addressing." },
static DECLCALLBACK(int) dbgcCmdGo(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdBrkAccess(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid access type '%s' for '%s'. Valid types are 'e', 'r', 'w' and 'i'",
return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid access size %RX64 for '%s'. 'x' access type requires size 1!",
iArg++;
iArg++;
iArg++;
return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "Failed to set access breakpoint at %RGv", Address.FlatPtr);
static DECLCALLBACK(int) dbgcCmdBrkClear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
while (pBp)
return rc;
static DECLCALLBACK(int) dbgcCmdBrkDisable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
return rc;
static DECLCALLBACK(int) dbgcCmdBrkEnable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
return rc;
char chType;
case DBGFBPTYPE_INT3:
case DBGFBPTYPE_REG:
case DBGFBPTYPE_REM:
int rc = DBGFR3AsSymbolByAddr(pUVM, pDbgc->hDbgAs, DBGFR3AddrFromFlat(pDbgc->pUVM, &Addr, pBp->GCPtr), &off, &Sym, NULL);
if (!off)
else if (off > 0)
if (pDbgcBp)
return VINF_SUCCESS;
static DECLCALLBACK(int) dbgcCmdBrkList(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
return rc;
static DECLCALLBACK(int) dbgcCmdBrkSet(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
iArg++;
iArg++;
iArg++;
static DECLCALLBACK(int) dbgcCmdBrkREM(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
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)
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." },