VirtualBox

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

Last change on this file since 10552 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

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