VirtualBox

Changeset 87788 in vbox


Ignore:
Timestamp:
Feb 18, 2021 3:12:31 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
142848
Message:

Debugger: Some early access to the DBGFR3FlowTrace* API for toying around, bugref:8650

Location:
trunk/src/VBox/Debugger
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Debugger/DBGCCmdWorkers.cpp

    r82968 r87788  
    228228}
    229229
     230
     231
     232
     233//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
     234//
     235//
     236//      F l o w T r a c e   M a n a g e m e n t
     237//
     238//
     239//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
     240
     241
     242
     243/**
     244 * Returns the trace flow module matching the given id or NULL if not found.
     245 *
     246 * @returns Pointer to the trace flow module or NULL if not found.
     247 * @param   pDbgc         The DBGC instance.
     248 * @param   iTraceFlowMod The trace flow module identifier.
     249 */
     250DECLHIDDEN(PDBGCTFLOW) dbgcFlowTraceModGet(PDBGC pDbgc, uint32_t iTraceFlowMod)
     251{
     252    PDBGCTFLOW pIt;
     253    RTListForEach(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow)
     254    {
     255        if (pIt->iTraceFlowMod == iTraceFlowMod)
     256            return pIt;
     257    }
     258
     259    return NULL;
     260}
     261
     262
     263/**
     264 * Inserts the given trace flow module into the list.
     265 *
     266 * @returns nothing.
     267 * @param   pDbgc         The DBGC instance.
     268 * @param   pTraceFlow    The trace flow module.
     269 */
     270static void dbgcFlowTraceModInsert(PDBGC pDbgc, PDBGCTFLOW pTraceFlow)
     271{
     272    PDBGCTFLOW pIt = RTListGetLast(&pDbgc->LstTraceFlowMods, DBGCTFLOW, NdTraceFlow);
     273
     274    if (   !pIt
     275        || pIt->iTraceFlowMod < pTraceFlow->iTraceFlowMod)
     276        RTListAppend(&pDbgc->LstTraceFlowMods, &pTraceFlow->NdTraceFlow);
     277    else
     278    {
     279        RTListForEach(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow)
     280        {
     281            if (pIt->iTraceFlowMod < pTraceFlow->iTraceFlowMod)
     282            {
     283                RTListNodeInsertBefore(&pIt->NdTraceFlow, &pTraceFlow->NdTraceFlow);
     284                break;
     285            }
     286        }
     287    }
     288}
     289
     290
     291/**
     292 * Returns the smallest free flow trace mod identifier.
     293 *
     294 * @returns Free flow trace mod identifier.
     295 * @param   pDbgc         The DBGC instance.
     296 */
     297static uint32_t dbgcFlowTraceModIdFindFree(PDBGC pDbgc)
     298{
     299    uint32_t iId = 0;
     300
     301    PDBGCTFLOW pIt;
     302    RTListForEach(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow)
     303    {
     304        PDBGCTFLOW pNext = RTListGetNext(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow);
     305        if (   (   pNext
     306                && pIt->iTraceFlowMod + 1 != pNext->iTraceFlowMod)
     307            || !pNext)
     308        {
     309            iId = pIt->iTraceFlowMod + 1;
     310            break;
     311        }
     312    }
     313
     314    return iId;
     315}
     316
     317
     318/**
     319 * Adds a flow trace module to the debugger console.
     320 *
     321 * @returns VBox status code.
     322 * @param   pDbgc         The DBGC instance.
     323 * @param   hFlowTraceMod The flow trace module to add.
     324 * @param   hFlow         The control flow graph to add.
     325 * @param   piId          Where to store the ID of the module on success.
     326 */
     327DECLHIDDEN(int) dbgcFlowTraceModAdd(PDBGC pDbgc, DBGFFLOWTRACEMOD hFlowTraceMod, DBGFFLOW hFlow, uint32_t *piId)
     328{
     329    /*
     330     * Add the module.
     331     */
     332    PDBGCTFLOW pTraceFlow = (PDBGCTFLOW)RTMemAlloc(sizeof(DBGCTFLOW));
     333    if (!pTraceFlow)
     334        return VERR_NO_MEMORY;
     335
     336    pTraceFlow->hTraceFlowMod = hFlowTraceMod;
     337    pTraceFlow->hFlow         = hFlow;
     338    pTraceFlow->iTraceFlowMod = dbgcFlowTraceModIdFindFree(pDbgc);
     339    dbgcFlowTraceModInsert(pDbgc, pTraceFlow);
     340
     341    *piId = pTraceFlow->iTraceFlowMod;
     342
     343    return VINF_SUCCESS;
     344}
     345
     346
     347/**
     348 * Deletes a breakpoint.
     349 *
     350 * @returns VBox status code.
     351 * @param   pDbgc       The DBGC instance.
     352 * @param   iTraceFlowMod The trace flow module identifier.
     353 */
     354DECLHIDDEN(int) dbgcFlowTraceModDelete(PDBGC pDbgc, uint32_t iFlowTraceMod)
     355{
     356    int rc = VINF_SUCCESS;
     357    PDBGCTFLOW pTraceFlow = dbgcFlowTraceModGet(pDbgc, iFlowTraceMod);
     358    if (pTraceFlow)
     359    {
     360        RTListNodeRemove(&pTraceFlow->NdTraceFlow);
     361        RTMemFree(pTraceFlow);
     362    }
     363    else
     364        rc = VERR_DBGC_BP_NOT_FOUND;
     365
     366    return rc;
     367}
     368
  • trunk/src/VBox/Debugger/DBGCEmulateCodeView.cpp

    r87776 r87788  
    2323#include <VBox/dbg.h>
    2424#include <VBox/vmm/dbgf.h>
     25#include <VBox/vmm/dbgfflowtrace.h>
    2526#include <VBox/vmm/pgm.h>
    2627#include <VBox/vmm/cpum.h>
     
    8687static FNDBGCCMD dbgcCmdUnassemble;
    8788static FNDBGCCMD dbgcCmdUnassembleCfg;
     89static FNDBGCCMD dbgcCmdTraceFlowClear;
     90static FNDBGCCMD dbgcCmdTraceFlowDisable;
     91static FNDBGCCMD dbgcCmdTraceFlowEnable;
     92static FNDBGCCMD dbgcCmdTraceFlowPrint;
     93static FNDBGCCMD dbgcCmdTraceFlowReset;
    8894
    8995
     
    371377};
    372378
     379/** 'tflowc' arguments. */
     380static const DBGCVARDESC    g_aArgTraceFlowClear[] =
     381{
     382    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     383    {  0,           ~0U,        DBGCVAR_CAT_NUMBER,     0,                              "#tf",          "Trace flow module number." },
     384    {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "all",          "All trace flow modules." },
     385};
     386
     387/** 'tflowd' arguments. */
     388static const DBGCVARDESC    g_aArgTraceFlowDisable[] =
     389{
     390    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     391    {  0,           ~0U,        DBGCVAR_CAT_NUMBER,     0,                              "#tf",          "Trace flow module number." },
     392    {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "all",          "All trace flow modules." },
     393};
     394
     395/** 'tflowe' arguments. */
     396static const DBGCVARDESC    g_aArgTraceFlowEnable[] =
     397{
     398    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     399    {  0,           1,          DBGCVAR_CAT_POINTER,       0,                           "address",      "Address where to start tracing." },
     400    {  0,           1,          DBGCVAR_CAT_OPTION_NUMBER, 0,                           "<Hits>",       "Maximum number of hits before the module is disabled." }
     401};
     402
     403/** 'tflowp', 'tflowr' arguments. */
     404static const DBGCVARDESC    g_aArgTraceFlowPrintReset[] =
     405{
     406    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     407    {  0,           ~0U,        DBGCVAR_CAT_NUMBER,     0,                              "#tf",          "Trace flow module number." },
     408    {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "all",          "All trace flow modules." },
     409};
    373410
    374411/** Command descriptors for the CodeView / WinDbg emulation.
     
    471508    { "sxr",        0,        0,        &g_aArgEventCtrlOpt[0], RT_ELEMENTS(g_aArgEventCtrlOpt), 0,  dbgcCmdEventCtrlReset, "",                    "Reset the settings to default for exceptions, exits and other events. All if no filter is specified." },
    472509    { "t",          0,        2,        &g_aArgStepTrace[0], RT_ELEMENTS(g_aArgStepTrace),  0,       dbgcCmdStepTrace,   "[count] [cmds]",       "Trace ." },
     510    { "tflowc",     1,       ~0U,       &g_aArgTraceFlowClear[0],   RT_ELEMENTS(g_aArgTraceFlowClear),   0, dbgcCmdTraceFlowClear,   "all | <tf#> [tf# []]", "Clears trace execution flow for the given method." },
     511    { "tflowd",     0,        1,        &g_aArgTraceFlowDisable[0], RT_ELEMENTS(g_aArgTraceFlowDisable), 0, dbgcCmdTraceFlowDisable, "all | <tf#> [tf# []]", "Disables trace execution flow for the given method." },
     512    { "tflowe",     0,        2,        &g_aArgTraceFlowEnable[0],  RT_ELEMENTS(g_aArgTraceFlowEnable),  0, dbgcCmdTraceFlowEnable,  "<addr> <hits>",        "Enable trace execution flow of the given method." },
     513    { "tflowp",     0,        1,        &g_aArgTraceFlowPrintReset[0],   RT_ELEMENTS(g_aArgTraceFlowPrintReset),   0, dbgcCmdTraceFlowPrint,   "all | <tf#> [tf# []]", "Prints the collected trace data of the given method." },
     514    { "tflowr",     0,        1,        &g_aArgTraceFlowPrintReset[0],   RT_ELEMENTS(g_aArgTraceFlowPrintReset),   0, dbgcCmdTraceFlowReset,   "all | <tf#> [tf# []]", "Resets the collected trace data of the given trace flow module." },
    473515    { "tr",         0,        0,        NULL,               0,                              0,       dbgcCmdStepTraceToggle, "",                 "Toggle displaying registers for tracing & stepping (no code executed)." },
    474516    { "ta",         1,        1,        &g_aArgStepTraceTo[0], RT_ELEMENTS(g_aArgStepTraceTo), 0,    dbgcCmdStepTraceTo, "<addr> [count] [cmds]","Trace to the given address." },
     
    62516293
    62526294
     6295/**
     6296 * @callback_method_impl{FNDBGCCMD, The 'tflowc' (clear trace flow) command.}
     6297 */
     6298static DECLCALLBACK(int) dbgcCmdTraceFlowClear(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
     6299{
     6300    DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
     6301
     6302    /*
     6303     * Enumerate the arguments.
     6304     */
     6305    PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
     6306    int     rc    = VINF_SUCCESS;
     6307    for (unsigned iArg = 0; iArg < cArgs && RT_SUCCESS(rc); iArg++)
     6308    {
     6309        if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
     6310        {
     6311            /* one */
     6312            uint32_t iFlowTraceMod = (uint32_t)paArgs[iArg].u.u64Number;
     6313            if (iFlowTraceMod == paArgs[iArg].u.u64Number)
     6314            {
     6315                PDBGCTFLOW pFlowTrace = dbgcFlowTraceModGet(pDbgc, iFlowTraceMod);
     6316                if (pFlowTrace)
     6317                {
     6318                    rc = DBGFR3FlowTraceModRelease(pFlowTrace->hTraceFlowMod);
     6319                    if (RT_FAILURE(rc))
     6320                        rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3FlowTraceModRelease failed for flow trace module %#x", iFlowTraceMod);
     6321                    rc = DBGFR3FlowRelease(pFlowTrace->hFlow);
     6322                    if (RT_FAILURE(rc))
     6323                        rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3FlowRelease failed for flow trace module %#x", iFlowTraceMod);
     6324                    dbgcFlowTraceModDelete(pDbgc, iFlowTraceMod);
     6325                }
     6326                else
     6327                    rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, VERR_NOT_FOUND, "Flow trace module %#x doesn't exist", iFlowTraceMod);
     6328            }
     6329            else
     6330                rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Flow trace mod id %RX64 is too large", paArgs[iArg].u.u64Number);
     6331        }
     6332        else if (!strcmp(paArgs[iArg].u.pszString, "all"))
     6333        {
     6334            /* all */
     6335            PDBGCTFLOW pIt, pItNext;
     6336            RTListForEachSafe(&pDbgc->LstTraceFlowMods, pIt, pItNext, DBGCTFLOW, NdTraceFlow)
     6337            {
     6338                int rc2 = DBGFR3FlowTraceModRelease(pIt->hTraceFlowMod);
     6339                if (RT_FAILURE(rc2))
     6340                    rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc2, "DBGFR3FlowTraceModDisable failed for flow trace module %#x", pIt->iTraceFlowMod);
     6341                dbgcFlowTraceModDelete(pDbgc, pIt->iTraceFlowMod);
     6342            }
     6343        }
     6344        else
     6345            rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid argument '%s'", paArgs[iArg].u.pszString);
     6346    }
     6347    return rc;
     6348}
     6349
     6350
     6351/**
     6352 * @callback_method_impl{FNDBGCCMD, The 'tflowd' (disable trace flow) command.}
     6353 */
     6354static DECLCALLBACK(int) dbgcCmdTraceFlowDisable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
     6355{
     6356    /*
     6357     * Enumerate the arguments.
     6358     */
     6359    RT_NOREF1(pUVM);
     6360    int rc = VINF_SUCCESS;
     6361    PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
     6362    for (unsigned iArg = 0; iArg < cArgs && RT_SUCCESS(rc); iArg++)
     6363    {
     6364        if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
     6365        {
     6366            /* one */
     6367            uint32_t iFlowTraceMod = (uint32_t)paArgs[iArg].u.u64Number;
     6368            if (iFlowTraceMod == paArgs[iArg].u.u64Number)
     6369            {
     6370                PDBGCTFLOW pFlowTrace = dbgcFlowTraceModGet(pDbgc, iFlowTraceMod);
     6371                if (pFlowTrace)
     6372                {
     6373                    rc = DBGFR3FlowTraceModDisable(pFlowTrace->hTraceFlowMod);
     6374                    if (RT_FAILURE(rc))
     6375                        rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3FlowTraceModDisable failed for flow trace module %#x", iFlowTraceMod);
     6376                }
     6377                else
     6378                    rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, VERR_NOT_FOUND, "Flow trace module %#x doesn't exist", iFlowTraceMod);
     6379            }
     6380            else
     6381                rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Breakpoint id %RX64 is too large", paArgs[iArg].u.u64Number);
     6382        }
     6383        else if (!strcmp(paArgs[iArg].u.pszString, "all"))
     6384        {
     6385            /* all */
     6386            PDBGCTFLOW pIt;
     6387            RTListForEach(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow)
     6388            {
     6389                int rc2 = DBGFR3FlowTraceModDisable(pIt->hTraceFlowMod);
     6390                if (RT_FAILURE(rc2))
     6391                    rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc2, "DBGFR3FlowTraceModDisable failed for flow trace module %#x",
     6392                                          pIt->iTraceFlowMod);
     6393            }
     6394        }
     6395        else
     6396            rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid argument '%s'", paArgs[iArg].u.pszString);
     6397    }
     6398    return rc;
     6399}
     6400
     6401
     6402/**
     6403 * @callback_method_impl{FNDBGCCMD, The 'tflowe' (enable trace flow) command.}
     6404 */
     6405static DECLCALLBACK(int) dbgcCmdTraceFlowEnable(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
     6406{
     6407    PDBGC pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
     6408
     6409    /*
     6410     * Validate input.
     6411     */
     6412    DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
     6413    DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, -1, cArgs <= 2);
     6414    DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, cArgs == 0 || DBGCVAR_ISPOINTER(paArgs[0].enmType));
     6415
     6416    if (!cArgs && !DBGCVAR_ISPOINTER(pDbgc->DisasmPos.enmType))
     6417        return DBGCCmdHlpFail(pCmdHlp, pCmd, "Don't know where to start disassembling");
     6418
     6419    /*
     6420     * Check the desired mode.
     6421     */
     6422    unsigned fFlags =  DBGF_DISAS_FLAGS_UNPATCHED_BYTES | DBGF_DISAS_FLAGS_ANNOTATE_PATCHED | DBGF_DISAS_FLAGS_DEFAULT_MODE;
     6423
     6424    /** @todo should use DBGFADDRESS for everything */
     6425
     6426    /*
     6427     * Find address.
     6428     */
     6429    if (!cArgs)
     6430    {
     6431        if (!DBGCVAR_ISPOINTER(pDbgc->DisasmPos.enmType))
     6432        {
     6433            /** @todo Batch query CS, RIP, CPU mode and flags. */
     6434            PVMCPU pVCpu = VMMR3GetCpuByIdU(pUVM, pDbgc->idCpu);
     6435            if (CPUMIsGuestIn64BitCode(pVCpu))
     6436            {
     6437                pDbgc->DisasmPos.enmType    = DBGCVAR_TYPE_GC_FLAT;
     6438                pDbgc->SourcePos.u.GCFlat   = CPUMGetGuestRIP(pVCpu);
     6439            }
     6440            else
     6441            {
     6442                pDbgc->DisasmPos.enmType     = DBGCVAR_TYPE_GC_FAR;
     6443                pDbgc->SourcePos.u.GCFar.off = CPUMGetGuestEIP(pVCpu);
     6444                pDbgc->SourcePos.u.GCFar.sel = CPUMGetGuestCS(pVCpu);
     6445                if (   (fFlags & DBGF_DISAS_FLAGS_MODE_MASK) == DBGF_DISAS_FLAGS_DEFAULT_MODE
     6446                    && (CPUMGetGuestEFlags(pVCpu) & X86_EFL_VM))
     6447                {
     6448                    fFlags &= ~DBGF_DISAS_FLAGS_MODE_MASK;
     6449                    fFlags |= DBGF_DISAS_FLAGS_16BIT_REAL_MODE;
     6450                }
     6451            }
     6452
     6453            fFlags |= DBGF_DISAS_FLAGS_CURRENT_GUEST;
     6454        }
     6455        else if ((fFlags & DBGF_DISAS_FLAGS_MODE_MASK) == DBGF_DISAS_FLAGS_DEFAULT_MODE && pDbgc->fDisasm)
     6456        {
     6457            fFlags &= ~DBGF_DISAS_FLAGS_MODE_MASK;
     6458            fFlags |= pDbgc->fDisasm & DBGF_DISAS_FLAGS_MODE_MASK;
     6459        }
     6460        pDbgc->DisasmPos.enmRangeType = DBGCVAR_RANGE_NONE;
     6461    }
     6462    else
     6463        pDbgc->DisasmPos = paArgs[0];
     6464    pDbgc->pLastPos = &pDbgc->DisasmPos;
     6465
     6466    /*
     6467     * Convert physical and host addresses to guest addresses.
     6468     */
     6469    RTDBGAS hDbgAs = pDbgc->hDbgAs;
     6470    int rc;
     6471    switch (pDbgc->DisasmPos.enmType)
     6472    {
     6473        case DBGCVAR_TYPE_GC_FLAT:
     6474        case DBGCVAR_TYPE_GC_FAR:
     6475            break;
     6476        case DBGCVAR_TYPE_GC_PHYS:
     6477            hDbgAs = DBGF_AS_PHYS;
     6478            /* fall thru */
     6479        case DBGCVAR_TYPE_HC_FLAT:
     6480        case DBGCVAR_TYPE_HC_PHYS:
     6481        {
     6482            DBGCVAR VarTmp;
     6483            rc = DBGCCmdHlpEval(pCmdHlp, &VarTmp, "%%(%Dv)", &pDbgc->DisasmPos);
     6484            if (RT_FAILURE(rc))
     6485                return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "failed to evaluate '%%(%Dv)'", &pDbgc->DisasmPos);
     6486            pDbgc->DisasmPos = VarTmp;
     6487            break;
     6488        }
     6489        default: AssertFailed(); break;
     6490    }
     6491
     6492    DBGFADDRESS CurAddr;
     6493    if (   (fFlags & DBGF_DISAS_FLAGS_MODE_MASK) == DBGF_DISAS_FLAGS_16BIT_REAL_MODE
     6494        && pDbgc->DisasmPos.enmType == DBGCVAR_TYPE_GC_FAR)
     6495        DBGFR3AddrFromFlat(pUVM, &CurAddr, ((uint32_t)pDbgc->DisasmPos.u.GCFar.sel << 4) + pDbgc->DisasmPos.u.GCFar.off);
     6496    else
     6497    {
     6498        rc = DBGCCmdHlpVarToDbgfAddr(pCmdHlp, &pDbgc->DisasmPos, &CurAddr);
     6499        if (RT_FAILURE(rc))
     6500            return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGCCmdHlpVarToDbgfAddr failed on '%Dv'", &pDbgc->DisasmPos);
     6501    }
     6502
     6503    DBGFFLOW hCfg;
     6504    rc = DBGFR3FlowCreate(pUVM, pDbgc->idCpu, &CurAddr, 0 /*cbDisasmMax*/,
     6505                          DBGF_FLOW_CREATE_F_TRY_RESOLVE_INDIRECT_BRANCHES, fFlags, &hCfg);
     6506    if (RT_SUCCESS(rc))
     6507    {
     6508        /* Create a probe. */
     6509        DBGFFLOWTRACEPROBE hFlowTraceProbe = NULL;
     6510        DBGFFLOWTRACEPROBE hFlowTraceProbeExit = NULL;
     6511        DBGFFLOWTRACEPROBEENTRY Entry;
     6512        DBGFFLOWTRACEMOD hFlowTraceMod = NULL;
     6513        uint32_t iTraceModId = 0;
     6514
     6515        RT_ZERO(Entry);
     6516        Entry.enmType = DBGFFLOWTRACEPROBEENTRYTYPE_DEBUGGER;
     6517
     6518        rc = DBGFR3FlowTraceProbeCreate(pUVM, NULL, &hFlowTraceProbe);
     6519        if (RT_SUCCESS(rc))
     6520            rc = DBGFR3FlowTraceProbeCreate(pUVM, NULL, &hFlowTraceProbeExit);
     6521        if (RT_SUCCESS(rc))
     6522            rc = DBGFR3FlowTraceProbeEntriesAdd(hFlowTraceProbeExit, &Entry, 1 /*cEntries*/);
     6523        if (RT_SUCCESS(rc))
     6524            rc = DBGFR3FlowTraceModCreateFromFlowGraph(pUVM, VMCPUID_ANY, hCfg, NULL,
     6525                                                       hFlowTraceProbe, hFlowTraceProbe,
     6526                                                       hFlowTraceProbeExit, &hFlowTraceMod);
     6527        if (RT_SUCCESS(rc))
     6528            rc = dbgcFlowTraceModAdd(pDbgc, hFlowTraceMod, hCfg, &iTraceModId);
     6529        if (RT_SUCCESS(rc))
     6530            rc = DBGFR3FlowTraceModEnable(hFlowTraceMod, 0, 0);
     6531        if (RT_SUCCESS(rc))
     6532            DBGCCmdHlpPrintf(pCmdHlp, "Enabled execution flow tracing %u at %RGv\n",
     6533                             iTraceModId, CurAddr.FlatPtr);
     6534
     6535        if (hFlowTraceProbe)
     6536            DBGFR3FlowTraceProbeRelease(hFlowTraceProbe);
     6537        if (hFlowTraceProbeExit)
     6538            DBGFR3FlowTraceProbeRelease(hFlowTraceProbeExit);
     6539    }
     6540    else
     6541        rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3FlowCreate failed on '%Dv'", &pDbgc->DisasmPos);
     6542
     6543    NOREF(pCmd);
     6544    return rc;
     6545}
     6546
     6547
     6548/**
     6549 * Enumerates and prints all records contained in the given flow tarce module.
     6550 *
     6551 * @returns VBox status code.
     6552 * @param   pCmd          The command.
     6553 * @param   pCmdHlp       The command helpers.
     6554 * @param   hFlowTraceMod The flow trace module to print.
     6555 * @param   hFlow         The control flow graph assoicated with the given module.
     6556 * @param   iFlowTraceMod The flow trace module identifier.
     6557 */
     6558static int dbgcCmdTraceFlowPrintOne(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, DBGFFLOWTRACEMOD hFlowTraceMod,
     6559                                    DBGFFLOW hFlow, uint32_t iFlowTraceMod)
     6560{
     6561    RT_NOREF(hFlow);
     6562
     6563    DBGFFLOWTRACEREPORT hFlowTraceReport;
     6564    int rc = DBGFR3FlowTraceModQueryReport(hFlowTraceMod, &hFlowTraceReport);
     6565    if (RT_SUCCESS(rc))
     6566    {
     6567        uint32_t cRecords = DBGFR3FlowTraceReportGetRecordCount(hFlowTraceReport);
     6568        DBGCCmdHlpPrintf(pCmdHlp, "Report for flow trace module %#x (%u records):\n",
     6569                         iFlowTraceMod, cRecords);
     6570
     6571        PDBGCFLOWBBDUMP paDumpBb = (PDBGCFLOWBBDUMP)RTMemTmpAllocZ(cRecords * sizeof(DBGCFLOWBBDUMP));
     6572        if (RT_LIKELY(paDumpBb))
     6573        {
     6574            /* Query the basic block referenced for each record and calculate the size. */
     6575            for (uint32_t i = 0; i < cRecords && RT_SUCCESS(rc); i++)
     6576            {
     6577                DBGFFLOWTRACERECORD hRec = NULL;
     6578                rc = DBGFR3FlowTraceReportQueryRecord(hFlowTraceReport, i, &hRec);
     6579                if (RT_SUCCESS(rc))
     6580                {
     6581                    DBGFADDRESS Addr;
     6582                    DBGFR3FlowTraceRecordGetAddr(hRec, &Addr);
     6583
     6584                    DBGFFLOWBB hFlowBb = NULL;
     6585                    rc = DBGFR3FlowQueryBbByAddress(hFlow, &Addr, &hFlowBb);
     6586                    if (RT_SUCCESS(rc))
     6587                        dbgcCmdUnassembleCfgDumpCalcBbSize(hFlowBb, &paDumpBb[i]);
     6588
     6589                    DBGFR3FlowTraceRecordRelease(hRec);
     6590                }
     6591            }
     6592
     6593            if (RT_SUCCESS(rc))
     6594            {
     6595                /* Calculate the ASCII screen dimensions and create one. */
     6596                uint32_t cchWidth = 0;
     6597                uint32_t cchHeight = 0;
     6598                for (unsigned i = 0; i < cRecords; i++)
     6599                {
     6600                    PDBGCFLOWBBDUMP pDumpBb = &paDumpBb[i];
     6601                    cchWidth = RT_MAX(cchWidth, pDumpBb->cchWidth);
     6602                    cchHeight += pDumpBb->cchHeight;
     6603
     6604                    /* Incomplete blocks don't have a successor. */
     6605                    if (DBGFR3FlowBbGetFlags(pDumpBb->hFlowBb) & DBGF_FLOW_BB_F_INCOMPLETE_ERR)
     6606                        continue;
     6607
     6608                    cchHeight += 2; /* For the arrow down to the next basic block. */
     6609                }
     6610
     6611
     6612                DBGCSCREEN hScreen = NULL;
     6613                rc = dbgcScreenAsciiCreate(&hScreen, cchWidth, cchHeight);
     6614                if (RT_SUCCESS(rc))
     6615                {
     6616                    uint32_t uY = 0;
     6617
     6618                    /* Dump the basic blocks and connections to the immediate successor. */
     6619                    for (unsigned i = 0; i < cRecords; i++)
     6620                    {
     6621                        paDumpBb[i].uStartX = (cchWidth - paDumpBb[i].cchWidth) / 2;
     6622                        paDumpBb[i].uStartY = uY;
     6623                        dbgcCmdUnassembleCfgDumpBb(&paDumpBb[i], hScreen);
     6624                        uY += paDumpBb[i].cchHeight;
     6625
     6626                        /* Incomplete blocks don't have a successor. */
     6627                        if (DBGFR3FlowBbGetFlags(paDumpBb[i].hFlowBb) & DBGF_FLOW_BB_F_INCOMPLETE_ERR)
     6628                            continue;
     6629
     6630                        if (DBGFR3FlowBbGetType(paDumpBb[i].hFlowBb) != DBGFFLOWBBENDTYPE_EXIT)
     6631                        {
     6632                            /* Draw the arrow down to the next block. */
     6633                            dbgcScreenAsciiDrawCharacter(hScreen, cchWidth / 2, uY,
     6634                                                         '|', DBGCSCREENCOLOR_BLUE_BRIGHT);
     6635                            uY++;
     6636                            dbgcScreenAsciiDrawCharacter(hScreen, cchWidth / 2, uY,
     6637                                                         'V', DBGCSCREENCOLOR_BLUE_BRIGHT);
     6638                            uY++;
     6639                        }
     6640                    }
     6641
     6642                    rc = dbgcScreenAsciiBlit(hScreen, dbgcCmdUnassembleCfgBlit, pCmdHlp, false /*fUseColor*/);
     6643                    dbgcScreenAsciiDestroy(hScreen);
     6644                }
     6645                else
     6646                    rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Failed to create virtual screen for flow trace module %#x", iFlowTraceMod);
     6647            }
     6648            else
     6649                rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Failed to query all records of flow trace module %#x", iFlowTraceMod);
     6650
     6651            for (unsigned i = 0; i < cRecords; i++)
     6652            {
     6653                if (paDumpBb[i].hFlowBb)
     6654                    DBGFR3FlowBbRelease(paDumpBb[i].hFlowBb);
     6655            }
     6656
     6657            RTMemTmpFree(paDumpBb);
     6658        }
     6659        else
     6660            rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Failed to allocate memory for %u records", cRecords);
     6661
     6662        DBGFR3FlowTraceReportRelease(hFlowTraceReport);
     6663    }
     6664    else
     6665        rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Failed to query report for flow trace module %#x", iFlowTraceMod);
     6666
     6667    return rc;
     6668}
     6669
     6670
     6671/**
     6672 * @callback_method_impl{FNDBGCCMD, The 'tflowp' (print trace flow) command.}
     6673 */
     6674static DECLCALLBACK(int) dbgcCmdTraceFlowPrint(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
     6675{
     6676    DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
     6677
     6678    /*
     6679     * Enumerate the arguments.
     6680     */
     6681    PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
     6682    int     rc    = VINF_SUCCESS;
     6683    for (unsigned iArg = 0; iArg < cArgs && RT_SUCCESS(rc); iArg++)
     6684    {
     6685        if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
     6686        {
     6687            /* one */
     6688            uint32_t iFlowTraceMod = (uint32_t)paArgs[iArg].u.u64Number;
     6689            if (iFlowTraceMod == paArgs[iArg].u.u64Number)
     6690            {
     6691                PDBGCTFLOW pFlowTrace = dbgcFlowTraceModGet(pDbgc, iFlowTraceMod);
     6692                if (pFlowTrace)
     6693                    rc = dbgcCmdTraceFlowPrintOne(pCmdHlp, pCmd, pFlowTrace->hTraceFlowMod,
     6694                                                  pFlowTrace->hFlow, pFlowTrace->iTraceFlowMod);
     6695                else
     6696                    rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, VERR_NOT_FOUND, "Flow trace module %#x doesn't exist", iFlowTraceMod);
     6697            }
     6698            else
     6699                rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Flow trace mod id %RX64 is too large", paArgs[iArg].u.u64Number);
     6700        }
     6701        else if (!strcmp(paArgs[iArg].u.pszString, "all"))
     6702        {
     6703            /* all */
     6704            PDBGCTFLOW pIt;
     6705            RTListForEach(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow)
     6706            {
     6707                rc = dbgcCmdTraceFlowPrintOne(pCmdHlp, pCmd, pIt->hTraceFlowMod,
     6708                                              pIt->hFlow, pIt->iTraceFlowMod);
     6709                if (RT_FAILURE(rc))
     6710                    break;
     6711            }
     6712        }
     6713        else
     6714            rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid argument '%s'", paArgs[iArg].u.pszString);
     6715    }
     6716    return rc;
     6717}
     6718
     6719
     6720/**
     6721 * @callback_method_impl{FNDBGCCMD, The 'tflowr' (reset trace flow) command.}
     6722 */
     6723static DECLCALLBACK(int) dbgcCmdTraceFlowReset(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
     6724{
     6725    DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
     6726
     6727    /*
     6728     * Enumerate the arguments.
     6729     */
     6730    PDBGC   pDbgc = DBGC_CMDHLP2DBGC(pCmdHlp);
     6731    int     rc    = VINF_SUCCESS;
     6732    for (unsigned iArg = 0; iArg < cArgs && RT_SUCCESS(rc); iArg++)
     6733    {
     6734        if (paArgs[iArg].enmType != DBGCVAR_TYPE_STRING)
     6735        {
     6736            /* one */
     6737            uint32_t iFlowTraceMod = (uint32_t)paArgs[iArg].u.u64Number;
     6738            if (iFlowTraceMod == paArgs[iArg].u.u64Number)
     6739            {
     6740                PDBGCTFLOW pFlowTrace = dbgcFlowTraceModGet(pDbgc, iFlowTraceMod);
     6741                if (pFlowTrace)
     6742                {
     6743                    rc = DBGFR3FlowTraceModClear(pFlowTrace->hTraceFlowMod);
     6744                    if (RT_FAILURE(rc))
     6745                        rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3FlowTraceModClear failed for flow trace module %#x", iFlowTraceMod);
     6746                }
     6747                else
     6748                    rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, VERR_NOT_FOUND, "Flow trace module %#x doesn't exist", iFlowTraceMod);
     6749            }
     6750            else
     6751                rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Flow trace mod id %RX64 is too large", paArgs[iArg].u.u64Number);
     6752        }
     6753        else if (!strcmp(paArgs[iArg].u.pszString, "all"))
     6754        {
     6755            /* all */
     6756            PDBGCTFLOW pIt;
     6757            RTListForEach(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow)
     6758            {
     6759                rc = DBGFR3FlowTraceModClear(pIt->hTraceFlowMod);
     6760                if (RT_FAILURE(rc))
     6761                    rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGFR3FlowTraceModClear failed for flow trace module %#x", pIt->iTraceFlowMod);
     6762            }
     6763        }
     6764        else
     6765            rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid argument '%s'", paArgs[iArg].u.pszString);
     6766    }
     6767    return rc;
     6768}
     6769
     6770
    62536771
    62546772/**
  • trunk/src/VBox/Debugger/DBGCInternal.h

    r86327 r87788  
    2828#include <VBox/dbg.h>
    2929#include <VBox/err.h>
    30 
     30#include <VBox/vmm/dbgf.h>
     31#include <VBox/vmm/dbgfflowtrace.h>
     32
     33#include <iprt/list.h>
    3134
    3235/*******************************************************************************
     
    9295/** Pointer to named variable. */
    9396typedef DBGCNAMEDVAR *PDBGCNAMEDVAR;
     97
     98
     99/**
     100 * Debugger console per trace flow data.
     101 */
     102typedef struct DBGCTFLOW
     103{
     104    /** Node for the trace flow module list. */
     105    RTLISTNODE       NdTraceFlow;
     106    /** Handle of the DGF trace flow module. */
     107    DBGFFLOWTRACEMOD hTraceFlowMod;
     108    /** The control flow graph for the module. */
     109    DBGFFLOW         hFlow;
     110    /** The trace flow module identifier. */
     111    uint32_t         iTraceFlowMod;
     112} DBGCTFLOW;
     113/** Pointer to the per trace flow data. */
     114typedef DBGCTFLOW *PDBGCTFLOW;
    94115
    95116
     
    190211    /** The list of breakpoints. (singly linked) */
    191212    PDBGCBP             pFirstBp;
     213    /** The list of known trace flow modules. */
     214    RTLISTANCHOR        LstTraceFlowMods;
    192215
    193216    /** Software interrupt events. */
     
    504527PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp);
    505528int     dbgcBpExec(PDBGC pDbgc, RTUINT iBp);
     529
     530DECLHIDDEN(PDBGCTFLOW) dbgcFlowTraceModGet(PDBGC pDbgc, uint32_t iTraceFlowMod);
     531DECLHIDDEN(int) dbgcFlowTraceModAdd(PDBGC pDbgc, DBGFFLOWTRACEMOD hFlowTraceMod, DBGFFLOW hFlow, uint32_t *piId);
     532DECLHIDDEN(int) dbgcFlowTraceModDelete(PDBGC pDbgc, uint32_t iFlowTraceMod);
    506533
    507534void    dbgcEvalInit(void);
  • trunk/src/VBox/Debugger/DBGConsole.cpp

    r86755 r87788  
    11651165    //pDbgc->pPlugInHead      = NULL;
    11661166    //pDbgc->pFirstBp         = NULL;
     1167    RTListInit(&pDbgc->LstTraceFlowMods);
    11671168    //pDbgc->abSearch         = {0};
    11681169    //pDbgc->cbSearch         = 0;
  • trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp

    r86101 r87788  
    2323
    2424#include <VBox/vmm/dbgf.h>
     25#include <VBox/vmm/dbgfflowtrace.h>
    2526VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromFlat(PUVM pUVM, PDBGFADDRESS pAddress, RTGCUINTPTR FlatPtr)
    2627{
     
    560561    return VERR_INTERNAL_ERROR;
    561562}
     563VMMR3DECL(int) DBGFR3FlowTraceModCreateFromFlowGraph(PUVM pUVM, VMCPUID idCpu, DBGFFLOW hFlow,
     564                                                     DBGFFLOWTRACEPROBE hFlowTraceProbeCommon,
     565                                                     DBGFFLOWTRACEPROBE hFlowTraceProbeEntry,
     566                                                     DBGFFLOWTRACEPROBE hFlowTraceProbeRegular,
     567                                                     DBGFFLOWTRACEPROBE hFlowTraceProbeExit,
     568                                                     PDBGFFLOWTRACEMOD phFlowTraceMod)
     569{
     570    return VERR_INTERNAL_ERROR;
     571}
     572VMMR3DECL(uint32_t) DBGFR3FlowTraceModRetain(DBGFFLOWTRACEMOD hFlowTraceMod)
     573{
     574    return 0;
     575}
     576VMMR3DECL(uint32_t) DBGFR3FlowTraceModRelease(DBGFFLOWTRACEMOD hFlowTraceMod)
     577{
     578    return 0;
     579}
     580VMMR3DECL(int) DBGFR3FlowTraceModEnable(DBGFFLOWTRACEMOD hFlowTraceMod, uint32_t cHits, uint32_t cRecordsMax)
     581{
     582    return VERR_INTERNAL_ERROR;
     583}
     584VMMR3DECL(int) DBGFR3FlowTraceModDisable(DBGFFLOWTRACEMOD hFlowTraceMod)
     585{
     586    return VERR_INTERNAL_ERROR;
     587}
     588VMMR3DECL(int) DBGFR3FlowTraceModQueryReport(DBGFFLOWTRACEMOD hFlowTraceMod,
     589                                             PDBGFFLOWTRACEREPORT phFlowTraceReport)
     590{
     591    return VERR_INTERNAL_ERROR;
     592}
     593VMMR3DECL(int) DBGFR3FlowTraceModClear(DBGFFLOWTRACEMOD hFlowTraceMod)
     594{
     595    return VERR_INTERNAL_ERROR;
     596}
     597VMMR3DECL(int) DBGFR3FlowTraceModAddProbe(DBGFFLOWTRACEMOD hFlowTraceMod, PCDBGFADDRESS pAddrProbe,
     598                                          DBGFFLOWTRACEPROBE hFlowTraceProbe, uint32_t fFlags)
     599{
     600    return VERR_INTERNAL_ERROR;
     601}
     602VMMR3DECL(int) DBGFR3FlowTraceProbeCreate(PUVM pUVM, const char *pszDescr, PDBGFFLOWTRACEPROBE phFlowTraceProbe)
     603{
     604    return VERR_INTERNAL_ERROR;
     605}
     606VMMR3DECL(uint32_t) DBGFR3FlowTraceProbeRetain(DBGFFLOWTRACEPROBE hFlowTraceProbe)
     607{
     608    return 0;
     609}
     610VMMR3DECL(uint32_t) DBGFR3FlowTraceProbeRelease(DBGFFLOWTRACEPROBE hFlowTraceProbe)
     611{
     612    return 0;
     613}
     614VMMR3DECL(int) DBGFR3FlowTraceProbeEntriesAdd(DBGFFLOWTRACEPROBE hFlowTraceProbe,
     615                                              PCDBGFFLOWTRACEPROBEENTRY paEntries, uint32_t cEntries)
     616{
     617    return VERR_INTERNAL_ERROR;
     618}
     619VMMR3DECL(uint32_t) DBGFR3FlowTraceReportRetain(DBGFFLOWTRACEREPORT hFlowTraceReport)
     620{
     621    return 0;
     622}
     623VMMR3DECL(uint32_t) DBGFR3FlowTraceReportRelease(DBGFFLOWTRACEREPORT hFlowTraceReport)
     624{
     625    return 0;
     626}
     627VMMR3DECL(uint32_t) DBGFR3FlowTraceReportGetRecordCount(DBGFFLOWTRACEREPORT hFlowTraceReport)
     628{
     629    return 0;
     630}
     631VMMR3DECL(int) DBGFR3FlowTraceReportQueryRecord(DBGFFLOWTRACEREPORT hFlowTraceReport, uint32_t idxRec, PDBGFFLOWTRACERECORD phFlowTraceRec)
     632{
     633    return VERR_INTERNAL_ERROR;
     634}
     635VMMR3DECL(int) DBGFR3FlowTraceReportQueryFiltered(DBGFFLOWTRACEREPORT hFlowTraceReport, uint32_t fFlags,
     636                                                  PDBGFFLOWTRACEREPORTFILTER paFilters, uint32_t cFilters,
     637                                                  DBGFFLOWTRACEREPORTFILTEROP enmOp,
     638                                                  PDBGFFLOWTRACEREPORT phFlowTraceReportFiltered)
     639{
     640    return VERR_INTERNAL_ERROR;
     641}
     642VMMR3DECL(int) DBGFR3FlowTraceReportEnumRecords(DBGFFLOWTRACEREPORT hFlowTraceReport,
     643                                                PFNDBGFFLOWTRACEREPORTENUMCLBK pfnEnum,
     644                                                void *pvUser)
     645{
     646    return VERR_INTERNAL_ERROR;
     647}
     648VMMR3DECL(uint32_t) DBGFR3FlowTraceRecordRetain(DBGFFLOWTRACERECORD hFlowTraceRecord)
     649{
     650    return 0;
     651}
     652VMMR3DECL(uint32_t) DBGFR3FlowTraceRecordRelease(DBGFFLOWTRACERECORD hFlowTraceRecord)
     653{
     654    return 0;
     655}
     656VMMR3DECL(uint64_t) DBGFR3FlowTraceRecordGetSeqNo(DBGFFLOWTRACERECORD hFlowTraceRecord)
     657{
     658    return 0;
     659}
     660VMMR3DECL(uint64_t) DBGFR3FlowTraceRecordGetTimestamp(DBGFFLOWTRACERECORD hFlowTraceRecord)
     661{
     662    return 0;
     663}
     664VMMR3DECL(PDBGFADDRESS) DBGFR3FlowTraceRecordGetAddr(DBGFFLOWTRACERECORD hFlowTraceRecord, PDBGFADDRESS pAddr)
     665{
     666    return NULL;
     667}
     668VMMR3DECL(DBGFFLOWTRACEPROBE) DBGFR3FlowTraceRecordGetProbe(DBGFFLOWTRACERECORD hFlowTraceRecord)
     669{
     670    return NULL;
     671}
     672VMMR3DECL(uint32_t) DBGFR3FlowTraceRecordGetValCount(DBGFFLOWTRACERECORD hFlowTraceRecord)
     673{
     674    return 0;
     675}
     676VMMR3DECL(PCDBGFFLOWTRACEPROBEVAL) DBGFR3FlowTraceRecordGetVals(DBGFFLOWTRACERECORD hFlowTraceRecord)
     677{
     678    return NULL;
     679}
     680VMMR3DECL(PCDBGFFLOWTRACEPROBEVAL) DBGFR3FlowTraceRecordGetValsCommon(DBGFFLOWTRACERECORD hFlowTraceRecord)
     681{
     682    return NULL;
     683}
     684VMMR3DECL(VMCPUID) DBGFR3FlowTraceRecordGetCpuId(DBGFFLOWTRACERECORD hFlowTraceRecord)
     685{
     686    return 0;
     687}
    562688
    563689VMMR3DECL(int) DBGFR3FormatBugCheck(PUVM pUVM, char *pszDetails, size_t cbDetails,
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette