diff options
Diffstat (limited to 'src/VBox/Debugger/DBGCCmdWorkers.cpp')
-rw-r--r-- | src/VBox/Debugger/DBGCCmdWorkers.cpp | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/src/VBox/Debugger/DBGCCmdWorkers.cpp b/src/VBox/Debugger/DBGCCmdWorkers.cpp new file mode 100644 index 00000000..c9ce701d --- /dev/null +++ b/src/VBox/Debugger/DBGCCmdWorkers.cpp @@ -0,0 +1,229 @@ +/* $Id: DBGCCmdWorkers.cpp $ */ +/** @file + * DBGC - Debugger Console, Command Worker Routines. + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DBGC +#include <VBox/dbg.h> +#include <VBox/vmm/dbgf.h> +#include <VBox/param.h> +#include <VBox/err.h> +#include <VBox/log.h> + +#include <iprt/alloc.h> +#include <iprt/string.h> +#include <iprt/assert.h> + +#include "DBGCInternal.h" + + + + +//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// +// +// +// B r e a k p o i n t M a n a g e m e n t +// +// +//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\// + + +/** + * Adds a breakpoint to the DBGC breakpoint list. + */ +int dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd) +{ + /* + * Check if it already exists. + */ + PDBGCBP pBp = dbgcBpGet(pDbgc, iBp); + if (pBp) + return VERR_DBGC_BP_EXISTS; + + /* + * Add the breakpoint. + */ + if (pszCmd) + pszCmd = RTStrStripL(pszCmd); + size_t cchCmd = pszCmd ? strlen(pszCmd) : 0; + pBp = (PDBGCBP)RTMemAlloc(RT_UOFFSETOF_DYN(DBGCBP, szCmd[cchCmd + 1])); + if (!pBp) + return VERR_NO_MEMORY; + if (cchCmd) + memcpy(pBp->szCmd, pszCmd, cchCmd + 1); + else + pBp->szCmd[0] = '\0'; + pBp->cchCmd = cchCmd; + pBp->iBp = iBp; + pBp->pNext = pDbgc->pFirstBp; + pDbgc->pFirstBp = pBp; + + return VINF_SUCCESS; +} + +/** + * Updates the a breakpoint. + * + * @returns VBox status code. + * @param pDbgc The DBGC instance. + * @param iBp The breakpoint to update. + * @param pszCmd The new command. + */ +int dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd) +{ + /* + * Find the breakpoint. + */ + PDBGCBP pBp = dbgcBpGet(pDbgc, iBp); + if (!pBp) + return VERR_DBGC_BP_NOT_FOUND; + + /* + * Do we need to reallocate? + */ + if (pszCmd) + pszCmd = RTStrStripL(pszCmd); + if (!pszCmd || !*pszCmd) + pBp->szCmd[0] = '\0'; + else + { + size_t cchCmd = strlen(pszCmd); + if (strlen(pBp->szCmd) >= cchCmd) + { + memcpy(pBp->szCmd, pszCmd, cchCmd + 1); + pBp->cchCmd = cchCmd; + } + else + { + /* + * Yes, let's do it the simple way... + */ + int rc = dbgcBpDelete(pDbgc, iBp); + AssertRC(rc); + return dbgcBpAdd(pDbgc, iBp, pszCmd); + } + } + return VINF_SUCCESS; +} + + +/** + * Deletes a breakpoint. + * + * @returns VBox status code. + * @param pDbgc The DBGC instance. + * @param iBp The breakpoint to delete. + */ +int dbgcBpDelete(PDBGC pDbgc, RTUINT iBp) +{ + /* + * Search thru the list, when found unlink and free it. + */ + PDBGCBP pBpPrev = NULL; + PDBGCBP pBp = pDbgc->pFirstBp; + for (; pBp; pBp = pBp->pNext) + { + if (pBp->iBp == iBp) + { + if (pBpPrev) + pBpPrev->pNext = pBp->pNext; + else + pDbgc->pFirstBp = pBp->pNext; + RTMemFree(pBp); + return VINF_SUCCESS; + } + pBpPrev = pBp; + } + + return VERR_DBGC_BP_NOT_FOUND; +} + + +/** + * Get a breakpoint. + * + * @returns Pointer to the breakpoint. + * @returns NULL if the breakpoint wasn't found. + * @param pDbgc The DBGC instance. + * @param iBp The breakpoint to get. + */ +PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp) +{ + /* + * Enumerate the list. + */ + PDBGCBP pBp = pDbgc->pFirstBp; + for (; pBp; pBp = pBp->pNext) + if (pBp->iBp == iBp) + return pBp; + return NULL; +} + + +/** + * Executes the command of a breakpoint. + * + * @returns VINF_DBGC_BP_NO_COMMAND if there is no command associated with the breakpoint. + * @returns VERR_DBGC_BP_NOT_FOUND if the breakpoint wasn't found. + * @returns VERR_BUFFER_OVERFLOW if the is not enough space in the scratch buffer for the command. + * @returns VBox status code from dbgcEvalCommand() otherwise. + * @param pDbgc The DBGC instance. + * @param iBp The breakpoint to execute. + */ +int dbgcBpExec(PDBGC pDbgc, RTUINT iBp) +{ + /* + * Find the breakpoint. + */ + PDBGCBP pBp = dbgcBpGet(pDbgc, iBp); + if (!pBp) + return VERR_DBGC_BP_NOT_FOUND; + + /* + * Anything to do? + */ + if (!pBp->cchCmd) + return VINF_DBGC_BP_NO_COMMAND; + + /* + * Execute the command. + * This means copying it to the scratch buffer and process it as if it + * were user input. We must save and restore the state of the scratch buffer. + */ + /* Save the scratch state. */ + char *pszScratch = pDbgc->pszScratch; + unsigned iArg = pDbgc->iArg; + + /* Copy the command to the scratch buffer. */ + size_t cbScratch = sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]); + if (pBp->cchCmd >= cbScratch) + return VERR_BUFFER_OVERFLOW; + memcpy(pDbgc->pszScratch, pBp->szCmd, pBp->cchCmd + 1); + + /* Execute the command. */ + pDbgc->pszScratch = pDbgc->pszScratch + pBp->cchCmd + 1; + int rc = dbgcEvalCommand(pDbgc, pszScratch, pBp->cchCmd, false /* fNoExecute */); + + /* Restore the scratch state. */ + pDbgc->iArg = iArg; + pDbgc->pszScratch = pszScratch; + + return rc; +} + |