VirtualBox

source: vbox/trunk/src/VBox/Main/MachineDebuggerImpl.cpp@ 5561

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

Added a pattern argument to the IMachineDebugger ResetStats and DumpStats methods.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.1 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
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#include "MachineDebuggerImpl.h"
19#include "ConsoleImpl.h"
20#include "Logging.h"
21
22#include <VBox/em.h>
23#include <VBox/patm.h>
24#include <VBox/csam.h>
25#include <VBox/vm.h>
26#include <VBox/tm.h>
27#include <VBox/err.h>
28#include <VBox/hwaccm.h>
29
30//
31// defines
32//
33
34
35//
36// globals
37//
38
39
40//
41// constructor / destructor
42//
43
44HRESULT MachineDebugger::FinalConstruct()
45{
46 mParent = NULL;
47 return S_OK;
48}
49
50void MachineDebugger::FinalRelease()
51{
52 if (isReady())
53 uninit();
54}
55
56//
57// public methods
58//
59
60/**
61 * Initializes the machine debugger object.
62 *
63 * @returns COM result indicator
64 * @param parent handle of our parent object
65 */
66HRESULT MachineDebugger::init(Console *parent)
67{
68 LogFlow(("MachineDebugger::init(): isReady=%d\n", isReady()));
69
70 ComAssertRet (parent, E_INVALIDARG);
71
72 AutoLock lock(this);
73 ComAssertRet (!isReady(), E_UNEXPECTED);
74
75 mParent = parent;
76 singlestepQueued = ~0;
77 recompileUserQueued = ~0;
78 recompileSupervisorQueued = ~0;
79 patmEnabledQueued = ~0;
80 csamEnabledQueued = ~0;
81 mLogEnabledQueued = ~0;
82 mVirtualTimeRateQueued = ~0;
83 fFlushMode = false;
84 setReady(true);
85 return S_OK;
86}
87
88/**
89 * Uninitializes the instance and sets the ready flag to FALSE.
90 * Called either from FinalRelease() or by the parent when it gets destroyed.
91 */
92void MachineDebugger::uninit()
93{
94 LogFlow(("MachineDebugger::uninit(): isReady=%d\n", isReady()));
95
96 AutoLock lock(this);
97 AssertReturn (isReady(), (void) 0);
98
99 setReady (false);
100}
101
102/**
103 * Returns the current singlestepping flag.
104 *
105 * @returns COM status code
106 * @param enabled address of result variable
107 */
108STDMETHODIMP MachineDebugger::COMGETTER(Singlestep)(BOOL *enabled)
109{
110 if (!enabled)
111 return E_POINTER;
112 AutoLock lock(this);
113 CHECK_READY();
114 /** @todo */
115 return E_NOTIMPL;
116}
117
118/**
119 * Sets the singlestepping flag.
120 *
121 * @returns COM status code
122 * @param enable new singlestepping flag
123 */
124STDMETHODIMP MachineDebugger::COMSETTER(Singlestep)(BOOL enable)
125{
126 AutoLock lock(this);
127 CHECK_READY();
128 /** @todo */
129 return E_NOTIMPL;
130}
131
132/**
133 * Resets VM statistics.
134 *
135 * @returns COM status code.
136 * @param aPattern The selection pattern. A bit similar to filename globbing.
137 */
138STDMETHODIMP MachineDebugger::ResetStats(INPTR BSTR aPattern)
139{
140 Console::SafeVMPtrQuiet pVM (mParent);
141 if (pVM.isOk())
142 STAMR3Reset(pVM, Utf8Str(aPattern).raw());
143 return S_OK;
144}
145
146/**
147 * Dumps VM statistics to the log.
148 *
149 * @returns COM status code.
150 * @param aPattern The selection pattern. A bit similar to filename globbing.
151 */
152STDMETHODIMP MachineDebugger::DumpStats(INPTR BSTR aPattern)
153{
154 Console::SafeVMPtrQuiet pVM (mParent);
155 if (pVM.isOk())
156 STAMR3Dump(pVM, Utf8Str(aPattern).raw());
157 return S_OK;
158}
159
160/**
161 * Get the VM statistics in an XML format.
162 *
163 * @returns COM status code.
164 * @param aPattern The selection pattern. A bit similar to filename globbing.
165 * @param aWithDescriptions Whether to include the descriptions.
166 * @param aStats The XML document containing the statistics.
167 */
168STDMETHODIMP MachineDebugger::GetStats(INPTR BSTR aPattern, BOOL aWithDescriptions, BSTR *aStats)
169{
170 Console::SafeVMPtrQuiet pVM (mParent);
171 if (!pVM.isOk())
172 return E_FAIL;
173
174 char *pszSnapshot;
175 int vrc = STAMR3Snapshot(pVM, Utf8Str(aPattern).raw(), &pszSnapshot, NULL, aWithDescriptions);
176 if (RT_FAILURE(vrc))
177 return vrc == VERR_NO_MEMORY ? E_OUTOFMEMORY : E_FAIL;
178
179 /** @todo this is horribly inefficient! And it's kinda difficult to tell whether it failed...
180 * Must use UTF-8 or ASCII here and completely avoid these two extra copy operations.
181 * Until that's done, this method is kind of useless for debugger statistics GUI because
182 * of the amount statistics in a debug build. */
183 Bstr(pszSnapshot).cloneTo(aStats);
184
185 return S_OK;
186}
187
188/**
189 * Returns the current recompile user mode code flag.
190 *
191 * @returns COM status code
192 * @param enabled address of result variable
193 */
194STDMETHODIMP MachineDebugger::COMGETTER(RecompileUser)(BOOL *enabled)
195{
196 if (!enabled)
197 return E_POINTER;
198 AutoLock lock(this);
199 CHECK_READY();
200 Console::SafeVMPtrQuiet pVM (mParent);
201 if (pVM.isOk())
202 *enabled = !EMIsRawRing3Enabled(pVM.raw());
203 else
204 *enabled = false;
205 return S_OK;
206}
207
208/**
209 * Sets the recompile user mode code flag.
210 *
211 * @returns COM status
212 * @param enable new user mode code recompile flag.
213 */
214STDMETHODIMP MachineDebugger::COMSETTER(RecompileUser)(BOOL enable)
215{
216 LogFlowThisFunc (("enable=%d\n", enable));
217
218 AutoLock lock(this);
219 CHECK_READY();
220
221 if (!fFlushMode)
222 {
223 // check if the machine is running
224 MachineState_T machineState;
225 mParent->COMGETTER(State)(&machineState);
226 if (machineState != MachineState_Running)
227 {
228 // queue the request
229 recompileUserQueued = enable;
230 return S_OK;
231 }
232 }
233
234 Console::SafeVMPtr pVM (mParent);
235 CheckComRCReturnRC (pVM.rc());
236
237 PVMREQ pReq;
238 EMRAWMODE rawModeFlag = enable ? EMRAW_RING3_DISABLE : EMRAW_RING3_ENABLE;
239 int rcVBox = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT,
240 (PFNRT)EMR3RawSetMode, 2, pVM.raw(), rawModeFlag);
241 if (VBOX_SUCCESS(rcVBox))
242 {
243 rcVBox = pReq->iStatus;
244 VMR3ReqFree(pReq);
245 }
246
247 if (VBOX_SUCCESS(rcVBox))
248 return S_OK;
249
250 AssertMsgFailed(("Could not set raw mode flags to %d, rcVBox = %Vrc\n",
251 rawModeFlag, rcVBox));
252 return E_FAIL;
253}
254
255/**
256 * Returns the current recompile supervisor code flag.
257 *
258 * @returns COM status code
259 * @param enabled address of result variable
260 */
261STDMETHODIMP MachineDebugger::COMGETTER(RecompileSupervisor)(BOOL *enabled)
262{
263 if (!enabled)
264 return E_POINTER;
265 AutoLock lock(this);
266 CHECK_READY();
267 Console::SafeVMPtrQuiet pVM (mParent);
268 if (pVM.isOk())
269 *enabled = !EMIsRawRing0Enabled(pVM.raw());
270 else
271 *enabled = false;
272 return S_OK;
273}
274
275/**
276 * Sets the new recompile supervisor code flag.
277 *
278 * @returns COM status code
279 * @param enable new recompile supervisor code flag
280 */
281STDMETHODIMP MachineDebugger::COMSETTER(RecompileSupervisor)(BOOL enable)
282{
283 LogFlowThisFunc (("enable=%d\n", enable));
284
285 AutoLock lock(this);
286 CHECK_READY();
287
288 if (!fFlushMode)
289 {
290 // check if the machine is running
291 MachineState_T machineState;
292 mParent->COMGETTER(State)(&machineState);
293 if (machineState != MachineState_Running)
294 {
295 // queue the request
296 recompileSupervisorQueued = enable;
297 return S_OK;
298 }
299 }
300
301 Console::SafeVMPtr pVM (mParent);
302 CheckComRCReturnRC (pVM.rc());
303
304 PVMREQ pReq;
305 EMRAWMODE rawModeFlag = enable ? EMRAW_RING0_DISABLE : EMRAW_RING0_ENABLE;
306 int rcVBox = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT,
307 (PFNRT)EMR3RawSetMode, 2, pVM.raw(), rawModeFlag);
308 if (VBOX_SUCCESS(rcVBox))
309 {
310 rcVBox = pReq->iStatus;
311 VMR3ReqFree(pReq);
312 }
313
314 if (VBOX_SUCCESS(rcVBox))
315 return S_OK;
316
317 AssertMsgFailed(("Could not set raw mode flags to %d, rcVBox = %Vrc\n",
318 rawModeFlag, rcVBox));
319 return E_FAIL;
320}
321
322/**
323 * Returns the current patch manager enabled flag.
324 *
325 * @returns COM status code
326 * @param enabled address of result variable
327 */
328STDMETHODIMP MachineDebugger::COMGETTER(PATMEnabled)(BOOL *enabled)
329{
330 if (!enabled)
331 return E_POINTER;
332 AutoLock lock(this);
333 CHECK_READY();
334 Console::SafeVMPtrQuiet pVM (mParent);
335 if (pVM.isOk())
336 *enabled = PATMIsEnabled(pVM.raw());
337 else
338 *enabled = false;
339 return S_OK;
340}
341
342/**
343 * Set the new patch manager enabled flag.
344 *
345 * @returns COM status code
346 * @param new patch manager enabled flag
347 */
348STDMETHODIMP MachineDebugger::COMSETTER(PATMEnabled)(BOOL enable)
349{
350 AutoLock lock(this);
351 CHECK_READY();
352 LogFlowThisFunc (("enable=%d\n", enable));
353
354 if (!fFlushMode)
355 {
356 // check if the machine is running
357 MachineState_T machineState;
358 mParent->COMGETTER(State)(&machineState);
359 if (machineState != MachineState_Running)
360 {
361 // queue the request
362 patmEnabledQueued = enable;
363 return S_OK;
364 }
365 }
366
367 Console::SafeVMPtr pVM (mParent);
368 CheckComRCReturnRC (pVM.rc());
369
370 PATMR3AllowPatching(pVM, enable);
371 return E_NOTIMPL;
372}
373
374/**
375 * Returns the current code scanner enabled flag.
376 *
377 * @returns COM status code
378 * @param enabled address of result variable
379 */
380STDMETHODIMP MachineDebugger::COMGETTER(CSAMEnabled)(BOOL *enabled)
381{
382 if (!enabled)
383 return E_POINTER;
384 AutoLock lock(this);
385 CHECK_READY();
386 Console::SafeVMPtrQuiet pVM (mParent);
387 if (pVM.isOk())
388 *enabled = CSAMIsEnabled(pVM.raw());
389 else
390 *enabled = false;
391 return S_OK;
392}
393
394/**
395 * Sets the new code scanner enabled flag.
396 *
397 * @returns COM status code
398 * @param enable new code scanner enabled flag
399 */
400STDMETHODIMP MachineDebugger::COMSETTER(CSAMEnabled)(BOOL enable)
401{
402 AutoLock lock(this);
403 CHECK_READY();
404 LogFlowThisFunc (("enable=%d\n", enable));
405
406 if (!fFlushMode)
407 {
408 // check if the machine is running
409 MachineState_T machineState;
410 mParent->COMGETTER(State)(&machineState);
411 if (machineState != MachineState_Running)
412 {
413 // queue the request
414 csamEnabledQueued = enable;
415 return S_OK;
416 }
417 }
418
419 Console::SafeVMPtr pVM (mParent);
420 CheckComRCReturnRC (pVM.rc());
421
422 int vrc;
423 if (enable)
424 vrc = CSAMEnableScanning(pVM);
425 else
426 vrc = CSAMDisableScanning(pVM);
427 if (VBOX_FAILURE(vrc))
428 {
429 /** @todo handle error case */
430 }
431 return S_OK;
432}
433
434/**
435 * Returns the log enabled / disabled status.
436 *
437 * @returns COM status code
438 * @param aEnabled address of result variable
439 */
440STDMETHODIMP MachineDebugger::COMGETTER(LogEnabled)(BOOL *aEnabled)
441{
442 if (!aEnabled)
443 return E_POINTER;
444 AutoLock alock(this);
445 CHECK_READY();
446 PRTLOGGER pLogInstance = RTLogDefaultInstance();
447 *aEnabled = pLogInstance && !(pLogInstance->fFlags & RTLOGFLAGS_DISABLED);
448 return S_OK;
449}
450
451/**
452 * Enables or disables logging.
453 *
454 * @returns COM status code
455 * @param aEnabled The new code log state.
456 */
457STDMETHODIMP MachineDebugger::COMSETTER(LogEnabled)(BOOL aEnabled)
458{
459 AutoLock alock(this);
460
461 CHECK_READY();
462 LogFlowThisFunc (("aEnabled=%d\n", aEnabled));
463
464 if (!fFlushMode)
465 {
466 // check if the machine is running
467 MachineState_T machineState;
468 mParent->COMGETTER(State)(&machineState);
469 if (machineState != MachineState_Running)
470 {
471 // queue the request
472 mLogEnabledQueued = aEnabled;
473 return S_OK;
474 }
475 }
476
477 Console::SafeVMPtr pVM (mParent);
478 CheckComRCReturnRC (pVM.rc());
479
480 int vrc = DBGFR3LogModifyFlags(pVM, aEnabled ? "enabled" : "disabled");
481 if (VBOX_FAILURE(vrc))
482 {
483 /** @todo handle error code. */
484 }
485 return S_OK;
486}
487
488/**
489 * Returns the current hardware virtualization flag.
490 *
491 * @returns COM status code
492 * @param enabled address of result variable
493 */
494STDMETHODIMP MachineDebugger::COMGETTER(HWVirtExEnabled)(BOOL *enabled)
495{
496 if (!enabled)
497 return E_POINTER;
498
499 AutoLock lock(this);
500 CHECK_READY();
501
502 Console::SafeVMPtrQuiet pVM (mParent);
503 if (pVM.isOk())
504 *enabled = HWACCMIsEnabled(pVM.raw());
505 else
506 *enabled = false;
507 return S_OK;
508}
509
510/**
511 * Returns the current virtual time rate.
512 *
513 * @returns COM status code.
514 * @param pct Where to store the rate.
515 */
516STDMETHODIMP MachineDebugger::COMGETTER(VirtualTimeRate)(ULONG *pct)
517{
518 if (!pct)
519 return E_POINTER;
520
521 AutoLock lock(this);
522 CHECK_READY();
523
524 Console::SafeVMPtrQuiet pVM (mParent);
525 if (pVM.isOk())
526 *pct = TMVirtualGetWarpDrive(pVM);
527 else
528 *pct = 100;
529 return S_OK;
530}
531
532/**
533 * Returns the current virtual time rate.
534 *
535 * @returns COM status code.
536 * @param pct Where to store the rate.
537 */
538STDMETHODIMP MachineDebugger::COMSETTER(VirtualTimeRate)(ULONG pct)
539{
540 if (pct < 2 || pct > 20000)
541 return E_INVALIDARG;
542
543 AutoLock lock(this);
544 CHECK_READY();
545
546 if (!fFlushMode)
547 {
548 // check if the machine is running
549 MachineState_T machineState;
550 mParent->COMGETTER(State)(&machineState);
551 if (machineState != MachineState_Running)
552 {
553 // queue the request
554 mVirtualTimeRateQueued = pct;
555 return S_OK;
556 }
557 }
558
559 Console::SafeVMPtr pVM (mParent);
560 CheckComRCReturnRC (pVM.rc());
561
562 int vrc = TMVirtualSetWarpDrive(pVM, pct);
563 if (VBOX_FAILURE(vrc))
564 {
565 /** @todo handle error code. */
566 }
567 return S_OK;
568}
569
570/**
571 * Hack for getting the VM handle.
572 * This is only temporary (promise) while prototyping the debugger.
573 *
574 * @returns COM status code
575 * @param vm Where to store the vm handle.
576 * Since there is no uintptr_t in COM, we're using the max integer.
577 * (No, ULONG is not pointer sized!)
578 */
579STDMETHODIMP MachineDebugger::COMGETTER(VM)(ULONG64 *vm)
580{
581 if (!vm)
582 return E_POINTER;
583
584 AutoLock lock(this);
585 CHECK_READY();
586
587 Console::SafeVMPtr pVM (mParent);
588 CheckComRCReturnRC (pVM.rc());
589
590 *vm = (uintptr_t)pVM.raw();
591
592 /*
593 * Note: pVM protection provided by SafeVMPtr is no more effective
594 * after we return from this method.
595 */
596
597 return S_OK;
598}
599
600//
601// "public-private" methods
602//
603void MachineDebugger::flushQueuedSettings()
604{
605 fFlushMode = true;
606 if (singlestepQueued != ~0)
607 {
608 COMSETTER(Singlestep)(singlestepQueued);
609 singlestepQueued = ~0;
610 }
611 if (recompileUserQueued != ~0)
612 {
613 COMSETTER(RecompileUser)(recompileUserQueued);
614 recompileUserQueued = ~0;
615 }
616 if (recompileSupervisorQueued != ~0)
617 {
618 COMSETTER(RecompileSupervisor)(recompileSupervisorQueued);
619 recompileSupervisorQueued = ~0;
620 }
621 if (patmEnabledQueued != ~0)
622 {
623 COMSETTER(PATMEnabled)(patmEnabledQueued);
624 patmEnabledQueued = ~0;
625 }
626 if (csamEnabledQueued != ~0)
627 {
628 COMSETTER(CSAMEnabled)(csamEnabledQueued);
629 csamEnabledQueued = ~0;
630 }
631 if (mLogEnabledQueued != ~0)
632 {
633 COMSETTER(LogEnabled)(mLogEnabledQueued);
634 mLogEnabledQueued = ~0;
635 }
636 if (mVirtualTimeRateQueued != ~(uint32_t)0)
637 {
638 COMSETTER(VirtualTimeRate)(mVirtualTimeRateQueued);
639 mVirtualTimeRateQueued = ~0;
640 }
641 fFlushMode = false;
642}
643
644//
645// private methods
646//
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