VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGCCmdWorkers.cpp

Last change on this file was 99739, checked in by vboxsync, 12 months ago

*: doxygen corrections (mostly about removing @returns from functions returning void).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.9 KB
Line 
1/* $Id: DBGCCmdWorkers.cpp 99739 2023-05-11 01:01:08Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Command Worker Routines.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DBGC
33#include <VBox/dbg.h>
34#include <VBox/vmm/dbgf.h>
35#include <VBox/param.h>
36#include <VBox/err.h>
37#include <VBox/log.h>
38
39#include <iprt/alloc.h>
40#include <iprt/string.h>
41#include <iprt/assert.h>
42
43#include "DBGCInternal.h"
44
45
46
47
48//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
49//
50//
51// B r e a k p o i n t M a n a g e m e n t
52//
53//
54//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
55
56
57/**
58 * Adds a breakpoint to the DBGC breakpoint list.
59 */
60int dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
61{
62 /*
63 * Check if it already exists.
64 */
65 PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
66 if (pBp)
67 return VERR_DBGC_BP_EXISTS;
68
69 /*
70 * Add the breakpoint.
71 */
72 if (pszCmd)
73 pszCmd = RTStrStripL(pszCmd);
74 size_t cchCmd = pszCmd ? strlen(pszCmd) : 0;
75 pBp = (PDBGCBP)RTMemAlloc(RT_UOFFSETOF_DYN(DBGCBP, szCmd[cchCmd + 1]));
76 if (!pBp)
77 return VERR_NO_MEMORY;
78 if (cchCmd)
79 memcpy(pBp->szCmd, pszCmd, cchCmd + 1);
80 else
81 pBp->szCmd[0] = '\0';
82 pBp->cchCmd = cchCmd;
83 pBp->iBp = iBp;
84 pBp->pNext = pDbgc->pFirstBp;
85 pDbgc->pFirstBp = pBp;
86
87 return VINF_SUCCESS;
88}
89
90/**
91 * Updates the a breakpoint.
92 *
93 * @returns VBox status code.
94 * @param pDbgc The DBGC instance.
95 * @param iBp The breakpoint to update.
96 * @param pszCmd The new command.
97 */
98int dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
99{
100 /*
101 * Find the breakpoint.
102 */
103 PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
104 if (!pBp)
105 return VERR_DBGC_BP_NOT_FOUND;
106
107 /*
108 * Do we need to reallocate?
109 */
110 if (pszCmd)
111 pszCmd = RTStrStripL(pszCmd);
112 if (!pszCmd || !*pszCmd)
113 pBp->szCmd[0] = '\0';
114 else
115 {
116 size_t cchCmd = strlen(pszCmd);
117 if (strlen(pBp->szCmd) >= cchCmd)
118 {
119 memcpy(pBp->szCmd, pszCmd, cchCmd + 1);
120 pBp->cchCmd = cchCmd;
121 }
122 else
123 {
124 /*
125 * Yes, let's do it the simple way...
126 */
127 int rc = dbgcBpDelete(pDbgc, iBp);
128 AssertRC(rc);
129 return dbgcBpAdd(pDbgc, iBp, pszCmd);
130 }
131 }
132 return VINF_SUCCESS;
133}
134
135
136/**
137 * Deletes a breakpoint.
138 *
139 * @returns VBox status code.
140 * @param pDbgc The DBGC instance.
141 * @param iBp The breakpoint to delete.
142 */
143int dbgcBpDelete(PDBGC pDbgc, RTUINT iBp)
144{
145 /*
146 * Search thru the list, when found unlink and free it.
147 */
148 PDBGCBP pBpPrev = NULL;
149 PDBGCBP pBp = pDbgc->pFirstBp;
150 for (; pBp; pBp = pBp->pNext)
151 {
152 if (pBp->iBp == iBp)
153 {
154 if (pBpPrev)
155 pBpPrev->pNext = pBp->pNext;
156 else
157 pDbgc->pFirstBp = pBp->pNext;
158 RTMemFree(pBp);
159 return VINF_SUCCESS;
160 }
161 pBpPrev = pBp;
162 }
163
164 return VERR_DBGC_BP_NOT_FOUND;
165}
166
167
168/**
169 * Get a breakpoint.
170 *
171 * @returns Pointer to the breakpoint.
172 * @returns NULL if the breakpoint wasn't found.
173 * @param pDbgc The DBGC instance.
174 * @param iBp The breakpoint to get.
175 */
176PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp)
177{
178 /*
179 * Enumerate the list.
180 */
181 PDBGCBP pBp = pDbgc->pFirstBp;
182 for (; pBp; pBp = pBp->pNext)
183 if (pBp->iBp == iBp)
184 return pBp;
185 return NULL;
186}
187
188
189/**
190 * Executes the command of a breakpoint.
191 *
192 * @returns VINF_DBGC_BP_NO_COMMAND if there is no command associated with the breakpoint.
193 * @returns VERR_DBGC_BP_NOT_FOUND if the breakpoint wasn't found.
194 * @returns VERR_BUFFER_OVERFLOW if the is not enough space in the scratch buffer for the command.
195 * @returns VBox status code from dbgcEvalCommand() otherwise.
196 * @param pDbgc The DBGC instance.
197 * @param iBp The breakpoint to execute.
198 */
199int dbgcBpExec(PDBGC pDbgc, RTUINT iBp)
200{
201 /*
202 * Find the breakpoint.
203 */
204 PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
205 if (!pBp)
206 return VERR_DBGC_BP_NOT_FOUND;
207
208 /*
209 * Anything to do?
210 */
211 if (!pBp->cchCmd)
212 return VINF_DBGC_BP_NO_COMMAND;
213
214 /*
215 * Execute the command.
216 * This means copying it to the scratch buffer and process it as if it
217 * were user input. We must save and restore the state of the scratch buffer.
218 */
219 /* Save the scratch state. */
220 char *pszScratch = pDbgc->pszScratch;
221 unsigned iArg = pDbgc->iArg;
222
223 /* Copy the command to the scratch buffer. */
224 size_t cbScratch = sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]);
225 if (pBp->cchCmd >= cbScratch)
226 return VERR_BUFFER_OVERFLOW;
227 memcpy(pDbgc->pszScratch, pBp->szCmd, pBp->cchCmd + 1);
228
229 /* Execute the command. */
230 pDbgc->pszScratch = pDbgc->pszScratch + pBp->cchCmd + 1;
231 int rc = dbgcEvalCommands(pDbgc, pszScratch, pBp->cchCmd, false /* fNoExecute */);
232
233 /* Restore the scratch state. */
234 pDbgc->iArg = iArg;
235 pDbgc->pszScratch = pszScratch;
236
237 return rc;
238}
239
240
241
242
243//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
244//
245//
246// F l o w T r a c e M a n a g e m e n t
247//
248//
249//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
250
251
252
253/**
254 * Returns the trace flow module matching the given id or NULL if not found.
255 *
256 * @returns Pointer to the trace flow module or NULL if not found.
257 * @param pDbgc The DBGC instance.
258 * @param iTraceFlowMod The trace flow module identifier.
259 */
260DECLHIDDEN(PDBGCTFLOW) dbgcFlowTraceModGet(PDBGC pDbgc, uint32_t iTraceFlowMod)
261{
262 PDBGCTFLOW pIt;
263 RTListForEach(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow)
264 {
265 if (pIt->iTraceFlowMod == iTraceFlowMod)
266 return pIt;
267 }
268
269 return NULL;
270}
271
272
273/**
274 * Inserts the given trace flow module into the list.
275 *
276 * @param pDbgc The DBGC instance.
277 * @param pTraceFlow The trace flow module.
278 */
279static void dbgcFlowTraceModInsert(PDBGC pDbgc, PDBGCTFLOW pTraceFlow)
280{
281 PDBGCTFLOW pIt = RTListGetLast(&pDbgc->LstTraceFlowMods, DBGCTFLOW, NdTraceFlow);
282
283 if ( !pIt
284 || pIt->iTraceFlowMod < pTraceFlow->iTraceFlowMod)
285 RTListAppend(&pDbgc->LstTraceFlowMods, &pTraceFlow->NdTraceFlow);
286 else
287 {
288 RTListForEach(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow)
289 {
290 if (pIt->iTraceFlowMod < pTraceFlow->iTraceFlowMod)
291 {
292 RTListNodeInsertBefore(&pIt->NdTraceFlow, &pTraceFlow->NdTraceFlow);
293 break;
294 }
295 }
296 }
297}
298
299
300/**
301 * Returns the smallest free flow trace mod identifier.
302 *
303 * @returns Free flow trace mod identifier.
304 * @param pDbgc The DBGC instance.
305 */
306static uint32_t dbgcFlowTraceModIdFindFree(PDBGC pDbgc)
307{
308 uint32_t iId = 0;
309
310 PDBGCTFLOW pIt;
311 RTListForEach(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow)
312 {
313 PDBGCTFLOW pNext = RTListGetNext(&pDbgc->LstTraceFlowMods, pIt, DBGCTFLOW, NdTraceFlow);
314 if ( ( pNext
315 && pIt->iTraceFlowMod + 1 != pNext->iTraceFlowMod)
316 || !pNext)
317 {
318 iId = pIt->iTraceFlowMod + 1;
319 break;
320 }
321 }
322
323 return iId;
324}
325
326
327/**
328 * Adds a flow trace module to the debugger console.
329 *
330 * @returns VBox status code.
331 * @param pDbgc The DBGC instance.
332 * @param hFlowTraceMod The flow trace module to add.
333 * @param hFlow The control flow graph to add.
334 * @param piId Where to store the ID of the module on success.
335 */
336DECLHIDDEN(int) dbgcFlowTraceModAdd(PDBGC pDbgc, DBGFFLOWTRACEMOD hFlowTraceMod, DBGFFLOW hFlow, uint32_t *piId)
337{
338 /*
339 * Add the module.
340 */
341 PDBGCTFLOW pTraceFlow = (PDBGCTFLOW)RTMemAlloc(sizeof(DBGCTFLOW));
342 if (!pTraceFlow)
343 return VERR_NO_MEMORY;
344
345 pTraceFlow->hTraceFlowMod = hFlowTraceMod;
346 pTraceFlow->hFlow = hFlow;
347 pTraceFlow->iTraceFlowMod = dbgcFlowTraceModIdFindFree(pDbgc);
348 dbgcFlowTraceModInsert(pDbgc, pTraceFlow);
349
350 *piId = pTraceFlow->iTraceFlowMod;
351
352 return VINF_SUCCESS;
353}
354
355
356/**
357 * Deletes a breakpoint.
358 *
359 * @returns VBox status code.
360 * @param pDbgc The DBGC instance.
361 * @param iTraceFlowMod The trace flow module identifier.
362 */
363DECLHIDDEN(int) dbgcFlowTraceModDelete(PDBGC pDbgc, uint32_t iTraceFlowMod)
364{
365 int rc = VINF_SUCCESS;
366 PDBGCTFLOW pTraceFlow = dbgcFlowTraceModGet(pDbgc, iTraceFlowMod);
367 if (pTraceFlow)
368 {
369 RTListNodeRemove(&pTraceFlow->NdTraceFlow);
370 RTMemFree(pTraceFlow);
371 }
372 else
373 rc = VERR_DBGC_BP_NOT_FOUND;
374
375 return rc;
376}
377
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use