Exemple #1
0
/**
 * Initializes the tracing.
 *
 * @returns VBox status code
 * @param   pVM                 The cross context VM structure.
 */
int dbgfR3TraceInit(PVM pVM)
{
    /*
     * Initialize the trace buffer handles.
     */
    Assert(NIL_RTTRACEBUF == (RTTRACEBUF)NULL);
    pVM->hTraceBufR3 = NIL_RTTRACEBUF;
    pVM->hTraceBufRC = NIL_RTRCPTR;
    pVM->hTraceBufR0 = NIL_RTR0PTR;

    /*
     * Check the config and enable tracing if requested.
     */
    PCFGMNODE pDbgfNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "DBGF");
#if defined(DEBUG) || defined(RTTRACE_ENABLED)
    bool const          fDefault        = false;
    const char * const  pszConfigDefault = "";
#else
    bool const          fDefault        = false;
    const char * const  pszConfigDefault = "";
#endif
    bool                fTracingEnabled;
    int rc = CFGMR3QueryBoolDef(pDbgfNode, "TracingEnabled", &fTracingEnabled, fDefault);
    AssertRCReturn(rc, rc);
    if (fTracingEnabled)
    {
        rc = dbgfR3TraceEnable(pVM, 0, 0);
        if (RT_SUCCESS(rc))
        {
            if (pDbgfNode)
            {
                char       *pszTracingConfig;
                rc = CFGMR3QueryStringAllocDef(pDbgfNode, "TracingConfig", &pszTracingConfig, pszConfigDefault);
                if (RT_SUCCESS(rc))
                {
                    rc = DBGFR3TraceConfig(pVM, pszTracingConfig);
                    if (RT_FAILURE(rc))
                        rc = VMSetError(pVM, rc, RT_SRC_POS, "TracingConfig=\"%s\" -> %Rrc", pszTracingConfig, rc);
                    MMR3HeapFree(pszTracingConfig);
                }
            }
            else
            {
                rc = DBGFR3TraceConfig(pVM, pszConfigDefault);
                if (RT_FAILURE(rc))
                    rc = VMSetError(pVM, rc, RT_SRC_POS, "TracingConfig=\"%s\" (default) -> %Rrc", pszConfigDefault, rc);
            }
        }
    }

    /*
     * Register a debug info item that will dump the trace buffer content.
     */
    if (RT_SUCCESS(rc))
        rc = DBGFR3InfoRegisterInternal(pVM, "tracebuf", "Display the trace buffer content. No arguments.", dbgfR3TraceInfo);

    return rc;
}
/**
 * Same as dbgfR3AsSearchEnv, except that the path is taken from the DBGF config
 * (CFGM).
 *
 * Nothing is done if the CFGM variable isn't set.
 *
 * @returns VBox status code.
 * @param   pszFilename     The filename.
 * @param   pszCfgValue     The name of the config variable (under /DBGF/).
 * @param   pfnOpen         The open callback function.
 * @param   pvUser          User argument for the callback.
 */
static int dbgfR3AsSearchCfgPath(PVM pVM, const char *pszFilename, const char *pszCfgValue, PFNDBGFR3ASSEARCHOPEN pfnOpen, void *pvUser)
{
    char *pszPath;
    int rc = CFGMR3QueryStringAllocDef(CFGMR3GetChild(CFGMR3GetRoot(pVM), "/DBGF"), pszCfgValue, &pszPath, NULL);
    if (RT_FAILURE(rc))
        return rc;
    if (!pszPath)
        return VERR_FILE_NOT_FOUND;
    rc = dbgfR3AsSearchPath(pszFilename, pszPath, pfnOpen, pvUser);
    MMR3HeapFree(pszPath);
    return rc;
}
/**
 * Initializes the address space parts of DBGF.
 *
 * @returns VBox status code.
 * @param   pUVM        The user mode VM handle.
 */
int dbgfR3AsInit(PUVM pUVM)
{
    Assert(pUVM->pVM);

    /*
     * Create the semaphore.
     */
    int rc = RTSemRWCreate(&pUVM->dbgf.s.hAsDbLock);
    AssertRCReturn(rc, rc);

    /*
     * Create the debugging config instance and set it up, defaulting to
     * deferred loading in order to keep things fast.
     */
    rc = RTDbgCfgCreate(&pUVM->dbgf.s.hDbgCfg, NULL, true /*fNativePaths*/);
    AssertRCReturn(rc, rc);
    rc = RTDbgCfgChangeUInt(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_FLAGS, RTDBGCFGOP_PREPEND,
                            RTDBGCFG_FLAGS_DEFERRED);
    AssertRCReturn(rc, rc);

    static struct
    {
        RTDBGCFGPROP    enmProp;
        const char     *pszEnvName;
        const char     *pszCfgName;
    } const s_aProps[] =
    {
        { RTDBGCFGPROP_FLAGS,               "VBOXDBG_FLAGS",            "Flags"             },
        { RTDBGCFGPROP_PATH,                "VBOXDBG_PATH",             "Path"              },
        { RTDBGCFGPROP_SUFFIXES,            "VBOXDBG_SUFFIXES",         "Suffixes"          },
        { RTDBGCFGPROP_SRC_PATH,            "VBOXDBG_SRC_PATH",         "SrcPath"           },
    };
    PCFGMNODE pCfgDbgf = CFGMR3GetChild(CFGMR3GetRootU(pUVM), "/DBGF");
    for (unsigned i = 0; i < RT_ELEMENTS(s_aProps); i++)
    {
        char szEnvValue[8192];
        rc = RTEnvGetEx(RTENV_DEFAULT, s_aProps[i].pszEnvName, szEnvValue, sizeof(szEnvValue), NULL);
        if (RT_SUCCESS(rc))
        {
            rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, s_aProps[i].enmProp, RTDBGCFGOP_PREPEND, szEnvValue);
            if (RT_FAILURE(rc))
                return VMR3SetError(pUVM, rc, RT_SRC_POS,
                                    "DBGF Config Error: %s=%s -> %Rrc", s_aProps[i].pszEnvName, szEnvValue, rc);
        }
        else if (rc != VERR_ENV_VAR_NOT_FOUND)
            return VMR3SetError(pUVM, rc, RT_SRC_POS,
                                "DBGF Config Error: Error querying env.var. %s: %Rrc", s_aProps[i].pszEnvName, rc);

        char *pszCfgValue;
        rc = CFGMR3QueryStringAllocDef(pCfgDbgf, s_aProps[i].pszCfgName, &pszCfgValue, NULL);
        if (RT_FAILURE(rc))
            return VMR3SetError(pUVM, rc, RT_SRC_POS,
                                "DBGF Config Error: Querying /DBGF/%s -> %Rrc", s_aProps[i].pszCfgName, rc);
        if (pszCfgValue)
        {
            rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, s_aProps[i].enmProp, RTDBGCFGOP_PREPEND, pszCfgValue);
            if (RT_FAILURE(rc))
                return VMR3SetError(pUVM, rc, RT_SRC_POS,
                                    "DBGF Config Error: /DBGF/%s=%s -> %Rrc", s_aProps[i].pszCfgName, pszCfgValue, rc);
        }
    }

    /*
     * Prepend the NoArch and VBoxDbgSyms directories to the path.
     */
    char szPath[RTPATH_MAX];
    rc = RTPathAppPrivateNoArch(szPath, sizeof(szPath));
    AssertRCReturn(rc, rc);
#ifdef RT_OS_DARWIN
    rc = RTPathAppend(szPath, sizeof(szPath), "../Resources/VBoxDbgSyms/");
#else
    rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_PATH, RTDBGCFGOP_PREPEND, szPath);
    AssertRCReturn(rc, rc);

    rc = RTPathAppend(szPath, sizeof(szPath), "VBoxDbgSyms/");
#endif
    AssertRCReturn(rc, rc);
    rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_PATH, RTDBGCFGOP_PREPEND, szPath);
    AssertRCReturn(rc, rc);

    /*
     * Create the standard address spaces.
     */
    RTDBGAS hDbgAs;
    rc = RTDbgAsCreate(&hDbgAs, 0, RTGCPTR_MAX, "Global");
    AssertRCReturn(rc, rc);
    rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS);
    AssertRCReturn(rc, rc);
    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_GLOBAL)] = hDbgAs;

    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_KERNEL)] = hDbgAs;

    rc = RTDbgAsCreate(&hDbgAs, 0, RTGCPHYS_MAX, "Physical");
    AssertRCReturn(rc, rc);
    rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS);
    AssertRCReturn(rc, rc);
    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_PHYS)] = hDbgAs;

    rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "HyperRawMode");
    AssertRCReturn(rc, rc);
    rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS);
    AssertRCReturn(rc, rc);
    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC)] = hDbgAs;
    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC_AND_GC_GLOBAL)] = hDbgAs;

    rc = RTDbgAsCreate(&hDbgAs, 0, RTR0PTR_MAX, "HyperRing0");
    AssertRCReturn(rc, rc);
    rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS);
    AssertRCReturn(rc, rc);
    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_R0)] = hDbgAs;

    return VINF_SUCCESS;
}
static int pdmacFileInitialize(PPDMASYNCCOMPLETIONEPCLASS pClassGlobals, PCFGMNODE pCfgNode)
{
    PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pClassGlobals;
    RTFILEAIOLIMITS                AioLimits; /** < Async I/O limitations. */

    int rc = RTFileAioGetLimits(&AioLimits);
#ifdef DEBUG
    if (RT_SUCCESS(rc) && RTEnvExist("VBOX_ASYNC_IO_FAILBACK"))
        rc = VERR_ENV_VAR_NOT_FOUND;
#endif
    if (RT_FAILURE(rc))
    {
        LogRel(("AIO: Async I/O manager not supported (rc=%Rrc). Falling back to simple manager\n",
                rc));
        pEpClassFile->enmMgrTypeOverride = PDMACEPFILEMGRTYPE_SIMPLE;
        pEpClassFile->enmEpBackendDefault = PDMACFILEEPBACKEND_BUFFERED;
    }
    else
    {
        pEpClassFile->uBitmaskAlignment   = AioLimits.cbBufferAlignment ? ~((RTR3UINTPTR)AioLimits.cbBufferAlignment - 1) : RTR3UINTPTR_MAX;
        pEpClassFile->cReqsOutstandingMax = AioLimits.cReqsOutstandingMax;

        if (pCfgNode)
        {
            /* Query the default manager type */
            char *pszVal = NULL;
            rc = CFGMR3QueryStringAllocDef(pCfgNode, "IoMgr", &pszVal, "Async");
            AssertLogRelRCReturn(rc, rc);

            rc = pdmacFileMgrTypeFromName(pszVal, &pEpClassFile->enmMgrTypeOverride);
            MMR3HeapFree(pszVal);
            if (RT_FAILURE(rc))
                return rc;

            LogRel(("AIOMgr: Default manager type is \"%s\"\n", pdmacFileMgrTypeToName(pEpClassFile->enmMgrTypeOverride)));

            /* Query default backend type */
            rc = CFGMR3QueryStringAllocDef(pCfgNode, "FileBackend", &pszVal, "NonBuffered");
            AssertLogRelRCReturn(rc, rc);

            rc = pdmacFileBackendTypeFromName(pszVal, &pEpClassFile->enmEpBackendDefault);
            MMR3HeapFree(pszVal);
            if (RT_FAILURE(rc))
                return rc;

            LogRel(("AIOMgr: Default file backend is \"%s\"\n", pdmacFileBackendTypeToName(pEpClassFile->enmEpBackendDefault)));

#ifdef RT_OS_LINUX
            if (   pEpClassFile->enmMgrTypeOverride == PDMACEPFILEMGRTYPE_ASYNC
                && pEpClassFile->enmEpBackendDefault == PDMACFILEEPBACKEND_BUFFERED)
            {
                LogRel(("AIOMgr: Linux does not support buffered async I/O, changing to non buffered\n"));
                pEpClassFile->enmEpBackendDefault = PDMACFILEEPBACKEND_NON_BUFFERED;
            }
#endif
        }
        else
        {
            /* No configuration supplied, set defaults */
            pEpClassFile->enmEpBackendDefault = PDMACFILEEPBACKEND_NON_BUFFERED;
            pEpClassFile->enmMgrTypeOverride  = PDMACEPFILEMGRTYPE_ASYNC;
        }
    }

    /* Init critical section. */
    rc = RTCritSectInit(&pEpClassFile->CritSect);

#ifdef VBOX_WITH_DEBUGGER
    /* Install the error injection handler. */
    if (RT_SUCCESS(rc))
    {
        rc = DBGCRegisterCommands(&g_aCmds[0], RT_ELEMENTS(g_aCmds));
        AssertRC(rc);
    }

#ifdef PDM_ASYNC_COMPLETION_FILE_WITH_DELAY
    rc = TMR3TimerCreateInternal(pEpClassFile->Core.pVM, TMCLOCK_REAL, pdmacR3TimerCallback, pEpClassFile, "AC Delay", &pEpClassFile->pTimer);
    AssertRC(rc);
    pEpClassFile->cMilliesNext = UINT64_MAX;
#endif
#endif

    return rc;
}