VirtualBox

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

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

Got the DBGC parser testcase framework going. enough fun for now.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.9 KB
Line 
1/** $Id: DBGCCmdWorkers.cpp 5686 2007-11-11 12:22:14Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Command Worker Routines.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * 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/dbgf.h>
24#include <VBox/vm.h>
25#include <VBox/vmm.h>
26#include <VBox/mm.h>
27#include <VBox/pgm.h>
28#include <VBox/selm.h>
29#include <VBox/dis.h>
30#include <VBox/param.h>
31#include <VBox/err.h>
32#include <VBox/log.h>
33
34#include <iprt/alloc.h>
35#include <iprt/alloca.h>
36#include <iprt/string.h>
37#include <iprt/assert.h>
38#include <iprt/ctype.h>
39
40#include "DBGCInternal.h"
41
42
43
44//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
45//
46//
47// V a r i a b l e M a n i p u l a t i o n
48//
49//
50//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
51
52
53
54/** @todo move me!*/
55void dbgcVarSetGCFlat(PDBGCVAR pVar, RTGCPTR GCFlat)
56{
57 if (pVar)
58 {
59 pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
60 pVar->u.GCFlat = GCFlat;
61 pVar->enmRangeType = DBGCVAR_RANGE_NONE;
62 pVar->u64Range = 0;
63 }
64}
65
66
67/** @todo move me!*/
68void dbgcVarSetGCFlatByteRange(PDBGCVAR pVar, RTGCPTR GCFlat, uint64_t cb)
69{
70 if (pVar)
71 {
72 pVar->enmType = DBGCVAR_TYPE_GC_FLAT;
73 pVar->u.GCFlat = GCFlat;
74 pVar->enmRangeType = DBGCVAR_RANGE_BYTES;
75 pVar->u64Range = cb;
76 }
77}
78
79
80/** @todo move me!*/
81void dbgcVarSetVar(PDBGCVAR pVar, PCDBGCVAR pVar2)
82{
83 if (pVar)
84 {
85 if (pVar2)
86 *pVar = *pVar2;
87 else
88 {
89 pVar->enmType = DBGCVAR_TYPE_UNKNOWN;
90 memset(&pVar->u, 0, sizeof(pVar->u));
91 pVar->enmRangeType = DBGCVAR_RANGE_NONE;
92 pVar->u64Range = 0;
93 }
94 }
95}
96
97
98/** @todo move me!*/
99void dbgcVarSetByteRange(PDBGCVAR pVar, uint64_t cb)
100{
101 if (pVar)
102 {
103 pVar->enmRangeType = DBGCVAR_RANGE_BYTES;
104 pVar->u64Range = cb;
105 }
106}
107
108
109/** @todo move me!*/
110void dbgcVarSetNoRange(PDBGCVAR pVar)
111{
112 if (pVar)
113 {
114 pVar->enmRangeType = DBGCVAR_RANGE_NONE;
115 pVar->u64Range = 0;
116 }
117}
118
119
120/**
121 * Converts a DBGC variable to a DBGF address.
122 *
123 * @returns VBox status code.
124 * @param pDbgc The DBGC instance.
125 * @param pVar The variable.
126 * @param pAddress Where to store the address.
127 */
128int dbgcVarToDbgfAddr(PDBGC pDbgc, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
129{
130 AssertReturn(pVar, VERR_INVALID_PARAMETER);
131 switch (pVar->enmType)
132 {
133 case DBGCVAR_TYPE_GC_FLAT:
134 DBGFR3AddrFromFlat(pDbgc->pVM, pAddress, pVar->u.GCFlat);
135 return VINF_SUCCESS;
136
137 case DBGCVAR_TYPE_NUMBER:
138 DBGFR3AddrFromFlat(pDbgc->pVM, pAddress, (RTGCUINTPTR)pVar->u.u64Number);
139 return VINF_SUCCESS;
140
141 case DBGCVAR_TYPE_GC_FAR:
142 return DBGFR3AddrFromSelOff(pDbgc->pVM, pAddress, pVar->u.GCFar.sel, pVar->u.GCFar.sel);
143
144 case DBGCVAR_TYPE_STRING:
145 case DBGCVAR_TYPE_SYMBOL:
146 {
147 DBGCVAR Var;
148 int rc = pDbgc->CmdHlp.pfnEval(&pDbgc->CmdHlp, &Var, "%%(%DV)", pVar);
149 if (VBOX_FAILURE(rc))
150 return rc;
151 return dbgcVarToDbgfAddr(pDbgc, &Var, pAddress);
152 }
153
154 case DBGCVAR_TYPE_GC_PHYS:
155 case DBGCVAR_TYPE_HC_FLAT:
156 case DBGCVAR_TYPE_HC_FAR:
157 case DBGCVAR_TYPE_HC_PHYS:
158 default:
159 return VERR_PARSE_CONVERSION_FAILED;
160 }
161}
162
163
164
165//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
166//
167//
168// B r e a k p o i n t M a n a g e m e n t
169//
170//
171//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
172
173
174/**
175 * Adds a breakpoint to the DBGC breakpoint list.
176 */
177int dbgcBpAdd(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
178{
179 /*
180 * Check if it already exists.
181 */
182 PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
183 if (pBp)
184 return VERR_DBGC_BP_EXISTS;
185
186 /*
187 * Add the breakpoint.
188 */
189 if (pszCmd)
190 pszCmd = RTStrStripL(pszCmd);
191 size_t cchCmd = pszCmd ? strlen(pszCmd) : 0;
192 pBp = (PDBGCBP)RTMemAlloc(RT_OFFSETOF(DBGCBP, szCmd[cchCmd + 1]));
193 if (!pBp)
194 return VERR_NO_MEMORY;
195 if (cchCmd)
196 memcpy(pBp->szCmd, pszCmd, cchCmd + 1);
197 else
198 pBp->szCmd[0] = '\0';
199 pBp->cchCmd = cchCmd;
200 pBp->iBp = iBp;
201 pBp->pNext = pDbgc->pFirstBp;
202 pDbgc->pFirstBp = pBp;
203
204 return VINF_SUCCESS;
205}
206
207/**
208 * Updates the a breakpoint.
209 *
210 * @returns VBox status code.
211 * @param pDbgc The DBGC instance.
212 * @param iBp The breakpoint to update.
213 * @param pszCmd The new command.
214 */
215int dbgcBpUpdate(PDBGC pDbgc, RTUINT iBp, const char *pszCmd)
216{
217 /*
218 * Find the breakpoint.
219 */
220 PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
221 if (!pBp)
222 return VERR_DBGC_BP_NOT_FOUND;
223
224 /*
225 * Do we need to reallocate?
226 */
227 if (pszCmd)
228 pszCmd = RTStrStripL(pszCmd);
229 if (!pszCmd || !*pszCmd)
230 pBp->szCmd[0] = '\0';
231 else
232 {
233 size_t cchCmd = strlen(pszCmd);
234 if (strlen(pBp->szCmd) >= cchCmd)
235 {
236 memcpy(pBp->szCmd, pszCmd, cchCmd + 1);
237 pBp->cchCmd = cchCmd;
238 }
239 else
240 {
241 /*
242 * Yes, let's do it the simple way...
243 */
244 int rc = dbgcBpDelete(pDbgc, iBp);
245 AssertRC(rc);
246 return dbgcBpAdd(pDbgc, iBp, pszCmd);
247 }
248 }
249 return VINF_SUCCESS;
250}
251
252
253/**
254 * Deletes a breakpoint.
255 *
256 * @returns VBox status code.
257 * @param pDbgc The DBGC instance.
258 * @param iBp The breakpoint to delete.
259 */
260int dbgcBpDelete(PDBGC pDbgc, RTUINT iBp)
261{
262 /*
263 * Search thru the list, when found unlink and free it.
264 */
265 PDBGCBP pBpPrev = NULL;
266 PDBGCBP pBp = pDbgc->pFirstBp;
267 for (; pBp; pBp = pBp->pNext)
268 {
269 if (pBp->iBp == iBp)
270 {
271 if (pBpPrev)
272 pBpPrev->pNext = pBp->pNext;
273 else
274 pDbgc->pFirstBp = pBp->pNext;
275 RTMemFree(pBp);
276 return VINF_SUCCESS;
277 }
278 pBpPrev = pBp;
279 }
280
281 return VERR_DBGC_BP_NOT_FOUND;
282}
283
284
285/**
286 * Get a breakpoint.
287 *
288 * @returns Pointer to the breakpoint.
289 * @returns NULL if the breakpoint wasn't found.
290 * @param pDbgc The DBGC instance.
291 * @param iBp The breakpoint to get.
292 */
293PDBGCBP dbgcBpGet(PDBGC pDbgc, RTUINT iBp)
294{
295 /*
296 * Enumerate the list.
297 */
298 PDBGCBP pBp = pDbgc->pFirstBp;
299 for (; pBp; pBp = pBp->pNext)
300 if (pBp->iBp == iBp)
301 return pBp;
302 return NULL;
303}
304
305
306/**
307 * Executes the command of a breakpoint.
308 *
309 * @returns VINF_DBGC_BP_NO_COMMAND if there is no command associated with the breakpoint.
310 * @returns VERR_DBGC_BP_NOT_FOUND if the breakpoint wasn't found.
311 * @returns VERR_BUFFER_OVERFLOW if the is not enough space in the scratch buffer for the command.
312 * @returns VBox status code from dbgcProcessCommand() other wise.
313 * @param pDbgc The DBGC instance.
314 * @param iBp The breakpoint to execute.
315 */
316int dbgcBpExec(PDBGC pDbgc, RTUINT iBp)
317{
318 /*
319 * Find the breakpoint.
320 */
321 PDBGCBP pBp = dbgcBpGet(pDbgc, iBp);
322 if (!pBp)
323 return VERR_DBGC_BP_NOT_FOUND;
324
325 /*
326 * Anything to do?
327 */
328 if (!pBp->cchCmd)
329 return VINF_DBGC_BP_NO_COMMAND;
330
331 /*
332 * Execute the command.
333 * This means copying it to the scratch buffer and process it as if it
334 * were user input. We must save and restore the state of the scratch buffer.
335 */
336 /* Save the scratch state. */
337 char *pszScratch = pDbgc->pszScratch;
338 unsigned iArg = pDbgc->iArg;
339
340 /* Copy the command to the scratch buffer. */
341 size_t cbScratch = sizeof(pDbgc->achScratch) - (pDbgc->pszScratch - &pDbgc->achScratch[0]);
342 if (pBp->cchCmd >= cbScratch)
343 return VERR_BUFFER_OVERFLOW;
344 memcpy(pDbgc->pszScratch, pBp->szCmd, pBp->cchCmd + 1);
345
346 /* Execute the command. */
347 pDbgc->pszScratch = pDbgc->pszScratch + pBp->cchCmd + 1;
348 int rc = dbgcProcessCommand(pDbgc, pszScratch, pBp->cchCmd, false /* fNoExecute */);
349
350 /* Restore the scratch state. */
351 pDbgc->iArg = iArg;
352 pDbgc->pszScratch = pszScratch;
353
354 return rc;
355}
356
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