/**
 * Creates a deferred loading stub for both image and debug info.
 *
 * @returns IPRT status code.
 * @param   pDbgMod             The debug module.
 * @param   pfnDeferred         The callback that will try load the image and
 *                              debug info.
 * @param   cbImage             The size of the image.
 * @param   hDbgCfg             The debug config handle.  Can be NIL.  A
 *                              reference will be retained.
 * @param   cbDeferred          The size of the deferred instance data, 0 if the
 *                              default structure is good enough.
 * @param   ppDeferred          Where to return the instance data. Can be NULL.
 */
DECLHIDDEN(int) rtDbgModDeferredCreate(PRTDBGMODINT pDbgMod, PFNRTDBGMODDEFERRED pfnDeferred, RTUINTPTR cbImage,
                                       RTDBGCFG hDbgCfg, size_t cbDeferred, PRTDBGMODDEFERRED *ppDeferred)
{
    AssertReturn(!pDbgMod->pDbgVt, VERR_DBG_MOD_IPE);

    if (cbDeferred < sizeof(RTDBGMODDEFERRED))
        cbDeferred = sizeof(RTDBGMODDEFERRED);
    PRTDBGMODDEFERRED pDeferred = (PRTDBGMODDEFERRED)RTMemAllocZ(cbDeferred);
    if (!pDeferred)
        return VERR_NO_MEMORY;

    pDeferred->cbImage     = cbImage;
    pDeferred->cRefs       = 1 + (pDbgMod->pImgVt == NULL);
    if (hDbgCfg != NIL_RTDBGCFG)
        RTDbgCfgRetain(hDbgCfg);
    pDeferred->hDbgCfg     = hDbgCfg;
    pDeferred->pfnDeferred = pfnDeferred;

    pDbgMod->pDbgVt             = &g_rtDbgModVtDbgDeferred;
    pDbgMod->pvDbgPriv          = pDeferred;
    if (!pDbgMod->pImgVt)
    {
        pDbgMod->pImgVt         = &g_rtDbgModVtImgDeferred;
        pDbgMod->pvImgPriv      = pDeferred;
    }
    pDbgMod->fDeferred          = true;
    pDbgMod->fDeferredFailed    = false;

    if (ppDeferred)
        *ppDeferred = pDeferred;
    return VINF_SUCCESS;
}
Exemplo n.º 2
0
/**
 * Make a console instance.
 *
 * This will not return until either an 'exit' command is issued or a error code
 * indicating connection loss is encountered.
 *
 * @returns VINF_SUCCESS if console termination caused by the 'exit' command.
 * @returns The VBox status code causing the console termination.
 *
 * @param   pUVM        The user mode VM handle.
 * @param   pBack       Pointer to the backend structure. This must contain
 *                      a full set of function pointers to service the console.
 * @param   fFlags      Reserved, must be zero.
 * @remarks A forced termination of the console is easiest done by forcing the
 *          callbacks to return fatal failures.
 */
DBGDECL(int) DBGCCreate(PUVM pUVM, PDBGCBACK pBack, unsigned fFlags)
{
    /*
     * Validate input.
     */
    AssertPtrNullReturn(pUVM, VERR_INVALID_VM_HANDLE);
    PVM pVM = NULL;
    if (pUVM)
    {
        pVM = VMR3GetVM(pUVM);
        AssertPtrReturn(pVM, VERR_INVALID_VM_HANDLE);
    }

    /*
     * Allocate and initialize instance data
     */
    PDBGC pDbgc;
    int rc = dbgcCreate(&pDbgc, pBack, fFlags);
    if (RT_FAILURE(rc))
        return rc;
    if (!HMR3IsEnabled(pUVM))
        pDbgc->hDbgAs = DBGF_AS_RC_AND_GC_GLOBAL;

    /*
     * Print welcome message.
     */
    rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
                                 "Welcome to the VirtualBox Debugger!\n");

    /*
     * Attach to the specified VM.
     */
    if (RT_SUCCESS(rc) && pUVM)
    {
        rc = dbgcReadConfig(pDbgc, pUVM);
        if (RT_SUCCESS(rc))
        {
            rc = DBGFR3Attach(pUVM);
            if (RT_SUCCESS(rc))
            {
                pDbgc->pVM   = pVM;
                pDbgc->pUVM  = pUVM;
                pDbgc->idCpu = 0;
                rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL,
                                             "Current VM is %08x, CPU #%u\n" /** @todo get and print the VM name! */
                                             , pDbgc->pVM, pDbgc->idCpu);
            }
            else
                rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "When trying to attach to VM %p\n", pDbgc->pVM);
        }
        else
            rc = pDbgc->CmdHlp.pfnVBoxError(&pDbgc->CmdHlp, rc, "Error reading configuration\n");
    }

    /*
     * Load plugins.
     */
    if (RT_SUCCESS(rc))
    {
        if (pVM)
            DBGFR3PlugInLoadAll(pDbgc->pUVM);
        dbgcEventInit(pDbgc);
        dbgcRunInitScripts(pDbgc);

        rc = pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "VBoxDbg> ");
        if (RT_SUCCESS(rc))
        {
            /*
             * Set debug config log callback.
             */
            RTDBGCFG    hDbgCfg = DBGFR3AsGetConfig(pUVM);
            if (   hDbgCfg != NIL_RTDBGCFG
                && RTDbgCfgRetain(hDbgCfg) != UINT32_MAX)
            {
                int rc2 = RTDbgCfgSetLogCallback(hDbgCfg, dbgcDbgCfgLogCallback, pDbgc);
                if (RT_FAILURE(rc2))
                {
                    hDbgCfg = NIL_RTDBGCFG;
                    RTDbgCfgRelease(hDbgCfg);
                }
            }
            else
                hDbgCfg = NIL_RTDBGCFG;


            /*
             * Run the debugger main loop.
             */
            rc = dbgcRun(pDbgc);


            /*
             * Remove debug config log callback.
             */
            if (hDbgCfg != NIL_RTDBGCFG)
            {
                RTDbgCfgSetLogCallback(hDbgCfg, NULL, NULL);
                RTDbgCfgRelease(hDbgCfg);
            }
        }
        dbgcEventTerm(pDbgc);
    }
    else
        pDbgc->CmdHlp.pfnPrintf(&pDbgc->CmdHlp, NULL, "\nDBGCCreate error: %Rrc\n", rc);


    /*
     * Cleanup console debugger session.
     */
    dbgcDestroy(pDbgc);
    return rc == VERR_DBGC_QUIT ? VINF_SUCCESS : rc;
}