VirtualBox

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

Last change on this file since 35650 was 35632, checked in by vboxsync, 14 years ago

DBGC: Simplified the status code handling around dbgcEvalCommand.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.8 KB
Line 
1/* $Id: DBGCCmdWorkers.cpp 35632 2011-01-19 15:55:05Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Command Worker Routines.
4 */
5
6/*
7 * Copyright (C) 2006-2011 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_DBGC
22#include <VBox/dbg.h>
23#include <VBox/vmm/dbgf.h>
24#include <VBox/param.h>
25#include <VBox/err.h>
26#include <VBox/log.h>
27
28#include <iprt/alloc.h>
29#include <iprt/string.h>
30#include <iprt/assert.h>
31
32#include "DBGCInternal.h"
33
34
35
36//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
37//
38//
39// V a r i a b l e M a n i p u l a t i o n
40//
41//
42//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
43
44
45
46/** @todo move me!*/
47void dbgcVarInit(PDBGCVAR pVar)
48{
49 if (pVar)
50 {
51 memset(pVar, 0, sizeof(*pVar));
52 AssertCompile(DBGCVAR_TYPE_UNKNOWN == 0);
53 AssertCompile(DBGCVAR_RANGE_NONE == 0);
54 }
55}
56
57
58/** @todo move me!*/
59void dbgcVarSetGCFlat(PDBGCVAR pVar, RTGCPTR GCFlat)
60{
61 if (pVar)
62 {
63 pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
64 memset(&pVar->u, 0, sizeof(pVar->u));
65 pVar->u.GCFlat = GCFlat;
66 pVar->enmRangeType = DBGCVAR_RANGE_NONE;
67 pVar->u64Range = 0;
68 }
69}
70
71
72/** @todo move me!*/
73void dbgcVarSetGCFlatByteRange(PDBGCVAR pVar, RTGCPTR GCFlat, uint64_t cb)
74{
75 if (pVar)
76 {
77 pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
78 memset(&pVar->u, 0, sizeof(pVar->u));
79 pVar->u.GCFlat = GCFlat;
80 pVar->enmRangeType = DBGCVAR_RANGE_BYTES;
81 pVar->u64Range = cb;
82 }
83}
84
85
86/** @todo move me!*/
87void dbgcVarSetU64(PDBGCVAR pVar, uint64_t u64)
88{
89 if (pVar)
90 {
91 pVar->enmType = DBGCVAR_TYPE_NUMBER;
92 memset(&pVar->u, 0, sizeof(pVar->u));
93 pVar->u.u64Number = u64;
94 pVar->enmRangeType = DBGCVAR_RANGE_NONE;
95 pVar->u64Range = 0;
96 }
97}
98
99
100/** @todo move me!*/
101void dbgcVarSetVar(PDBGCVAR pVar, PCDBGCVAR pVar2)
102{
103 if (pVar)
104 {
105 if (pVar2)
106 *pVar = *pVar2;
107 else
108 {
109 pVar->enmType = DBGCVAR_TYPE_UNKNOWN;
110 memset(&pVar->u, 0, sizeof(pVar->u));
111 pVar->enmRangeType = DBGCVAR_RANGE_NONE;
112 pVar->u64Range = 0;
113 }
114 }
115}
116
117/** @todo move me!*/
118void dbgcVarSetDbgfAddr(PDBGCVAR pVar, PCDBGFADDRESS pAddress)
119{
120 if (pVar)
121 {
122 memset(&pVar->u, 0, sizeof(pVar->u));
123
124 Assert(!pAddress || DBGFADDRESS_IS_VALID(pAddress));
125 if (pAddress && DBGFADDRESS_IS_VALID(pAddress))
126 {
127 switch (pAddress->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK)
128 {
129 case DBGFADDRESS_FLAGS_FAR16:
130 case DBGFADDRESS_FLAGS_FAR32:
131 case DBGFADDRESS_FLAGS_FAR64:
132 pVar->enmType = DBGCVAR_TYPE_GC_FAR;
133 pVar->u.GCFar.off = pAddress->off;
134 pVar->u.GCFar.sel = pAddress->Sel;
135 break;
136
137 case DBGFADDRESS_FLAGS_FLAT:
138 pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
139 pVar->u.GCFlat = pAddress->FlatPtr;
140 break;
141
142 case DBGFADDRESS_FLAGS_PHYS:
143 pVar->enmType = DBGCVAR_TYPE_GC_PHYS;
144 pVar->u.GCPhys = pAddress->FlatPtr;
145 break;
146
147 default:
148 AssertFailed();
149 pVar->enmType = DBGCVAR_TYPE_UNKNOWN;
150 break;
151 }
152 }
153 else
154 pVar->enmType = DBGCVAR_TYPE_UNKNOWN;
155 pVar->enmRangeType = DBGCVAR_RANGE_NONE;
156 pVar->u64Range = 0;
157 }
158}
159
160
161/** @todo move me!*/
162void dbgcVarSetByteRange(PDBGCVAR pVar, uint64_t cb)
163{
164 if (pVar)
165 {
166 pVar->enmRangeType = DBGCVAR_RANGE_BYTES;
167 pVar->u64Range = cb;
168 }
169}
170
171
172/** @todo move me!*/
173void dbgcVarSetNoRange(PDBGCVAR pVar)
174{
175 if (pVar)
176 {
177 pVar->enmRangeType = DBGCVAR_RANGE_NONE;
178 pVar->u64Range = 0;
179 }
180}
181
182
183/**
184 * Converts a DBGC variable to a DBGF address.
185 *
186 * @returns VBox status code.
187 * @param pDbgc The DBGC instance.
188 * @param pVar The variable.
189 * @param pAddress Where to store the address.
190 */
191int dbgcVarToDbgfAddr(PDBGC pDbgc, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
192{
193 AssertReturn(pVar, VERR_INVALID_PARAMETER);
194 switch (pVar->enmType)
195 {
196 case DBGCVAR_TYPE_GC_FLAT:
197 DBGFR3AddrFromFlat(pDbgc->pVM, pAddress, pVar->u.GCFlat);
198 return VINF_SUCCESS;
199
200 case DBGCVAR_TYPE_NUMBER:
201 DBGFR3AddrFromFlat(pDbgc->pVM, pAddress, (RTGCUINTPTR)pVar->u.u64Number);
202 return VINF_SUCCESS;
203
204 case DBGCVAR_TYPE_GC_FAR:
205 return DBGFR3AddrFromSelOff(pDbgc->pVM, pDbgc->idCpu, pAddress, pVar->u.GCFar.sel, pVar->u.GCFar.off);
206
207 case DBGCVAR_TYPE_GC_PHYS:
208 DBGFR3AddrFromPhys(pDbgc->pVM, pAddress, pVar->u.GCPhys);
209 return VINF_SUCCESS;
210
211 case DBGCVAR_TYPE_STRING:
212 case DBGCVAR_TYPE_SYMBOL:
213 {
214 DBGCVAR Var;
215 int rc = DBGCCmdHlpEval(&pDbgc->CmdHlp, &Var, "%%(%DV)", pVar);
216 if (RT_FAILURE(rc))
217 return rc;
218 return dbgcVarToDbgfAddr(pDbgc, &Var, pAddress);
219 }
220
221 case DBGCVAR_TYPE_HC_FLAT:
222 case DBGCVAR_TYPE_HC_PHYS:
223 default:
224 return VERR_PARSE_CONVERSION_FAILED;
225 }
226}
227
228
229
230//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
231//
232//
233// B r e a k p o i n t M a n a g e m e n t
234//
235//
236//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
237
238
239/**
240 * Adds a breakpoint to the DBGC breakpoint list.
241 */
242int dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
243{
244 /*
245 * Check if it already exists.
246 */
247 PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
248 if (pBp)
249 return VERR_DBGC_BP_EXISTS;
250
251 /*
252 * Add the breakpoint.
253 */
254 if (pszCmd)
255 pszCmd = RTStrStripL(pszCmd);
256 size_t cchCmd = pszCmd ? strlen(pszCmd) : 0;
257 pBp = (PDBGCBP)RTMemAlloc(RT_OFFSETOF(DBGCBP, szCmd[cchCmd + 1]));
258 if (!pBp)
259 return VERR_NO_MEMORY;
260 if (cchCmd)
261 memcpy(pBp->szCmd, pszCmd, cchCmd + 1);
262 else
263 pBp->szCmd[0] = '\0';
264 pBp->cchCmd = cchCmd;
265 pBp->iBp = iBp;
266 pBp->pNext = pDbgc->pFirstBp;
267 pDbgc->pFirstBp = pBp;
268
269 return VINF_SUCCESS;
270}
271
272/**
273 * Updates the a breakpoint.
274 *
275 * @returns VBox status code.
276 * @param pDbgc The DBGC instance.
277 * @param iBp The breakpoint to update.
278 * @param pszCmd The new command.
279 */
280int dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
281{
282 /*
283 * Find the breakpoint.
284 */
285 PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
286 if (!pBp)
287 return VERR_DBGC_BP_NOT_FOUND;
288
289 /*
290 * Do we need to reallocate?
291 */
292 if (pszCmd)
293 pszCmd = RTStrStripL(pszCmd);
294 if (!pszCmd || !*pszCmd)
295 pBp->szCmd[0] = '\0';
296 else
297 {
298 size_t cchCmd = strlen(pszCmd);
299 if (strlen(pBp->szCmd) >= cchCmd)
300 {
301 memcpy(pBp->szCmd, pszCmd, cchCmd + 1);
302 pBp->cchCmd = cchCmd;
303 }
304 else
305 {
306 /*
307 * Yes, let's do it the simple way...
308 */
309 int rc = dbgcBpDelete(pDbgc, iBp);
310 AssertRC(rc);
311 return dbgcBpAdd(pDbgc, iBp, pszCmd);
312 }
313 }
314 return VINF_SUCCESS;
315}
316
317
318/**
319 * Deletes a breakpoint.
320 *
321 * @returns VBox status code.
322 * @param pDbgc The DBGC instance.
323 * @param iBp The breakpoint to delete.
324 */
325int dbgcBpDelete(PDBGC pDbgc, RTUINT iBp)
326{
327 /*
328 * Search thru the list, when found unlink and free it.
329 */
330 PDBGCBP pBpPrev = NULL;
331 PDBGCBP pBp = pDbgc->pFirstBp;
332 for (; pBp; pBp = pBp->pNext)
333 {
334 if (pBp->iBp == iBp)
335 {
336 if (pBpPrev)
337 pBpPrev->pNext = pBp->pNext;
338 else
339 pDbgc->pFirstBp = pBp->pNext;
340 RTMemFree(pBp);
341 return VINF_SUCCESS;
342 }
343 pBpPrev = pBp;
344 }
345
346 return VERR_DBGC_BP_NOT_FOUND;
347}
348
349
350/**
351 * Get a breakpoint.
352 *
353 * @returns Pointer to the breakpoint.
354 * @returns NULL if the breakpoint wasn't found.
355 * @param pDbgc The DBGC instance.
356 * @param iBp The breakpoint to get.
357 */
358PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp)
359{
360 /*
361 * Enumerate the list.
362 */
363 PDBGCBP pBp = pDbgc->pFirstBp;
364 for (; pBp; pBp = pBp->pNext)
365 if (pBp->iBp == iBp)
366 return pBp;
367 return NULL;
368}
369
370
371/**
372 * Executes the command of a breakpoint.
373 *
374 * @returns VINF_DBGC_BP_NO_COMMAND if there is no command associated with the breakpoint.
375 * @returns VERR_DBGC_BP_NOT_FOUND if the breakpoint wasn't found.
376 * @returns VERR_BUFFER_OVERFLOW if the is not enough space in the scratch buffer for the command.
377 * @returns VBox status code from dbgcEvalCommand() otherwise.
378 * @param pDbgc The DBGC instance.
379 * @param iBp The breakpoint to execute.
380 */
381int dbgcBpExec(PDBGC pDbgc, RTUINT iBp)
382{
383 /*
384 * Find the breakpoint.
385 */
386 PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
387 if (!pBp)
388 return VERR_DBGC_BP_NOT_FOUND;
389
390 /*
391 * Anything to do?
392 */
393 if (!pBp->cchCmd)
394 return VINF_DBGC_BP_NO_COMMAND;
395
396 /*
397 * Execute the command.
398 * This means copying it to the scratch buffer and process it as if it
399 * were user input. We must save and restore the state of the scratch buffer.
400 */
401 /* Save the scratch state. */
402 char *pszScratch = pDbgc->pszScratch;
403 unsigned iArg = pDbgc->iArg;
404
405 /* Copy the command to the scratch buffer. */
406 size_t cbScratch = sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]);
407 if (pBp->cchCmd >= cbScratch)
408 return VERR_BUFFER_OVERFLOW;
409 memcpy(pDbgc->pszScratch, pBp->szCmd, pBp->cchCmd + 1);
410
411 /* Execute the command. */
412 pDbgc->pszScratch = pDbgc->pszScratch + pBp->cchCmd + 1;
413 int rc = dbgcEvalCommand(pDbgc, pszScratch, pBp->cchCmd, false /* fNoExecute */);
414
415 /* Restore the scratch state. */
416 pDbgc->iArg = iArg;
417 pDbgc->pszScratch = pszScratch;
418
419 return rc;
420}
421
Note: See TracBrowser for help on using the repository browser.

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