VirtualBox

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

Last change on this file since 33682 was 31530, checked in by vboxsync, 14 years ago

Debugger: Updated the file headers.

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