VirtualBox

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

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

Merged dmik/s2 branch (r25959:26751) to the trunk.

  • 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 (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#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,
176 !!aWithDescriptions);
177 if (RT_FAILURE(vrc))
178 return vrc == VERR_NO_MEMORY ? E_OUTOFMEMORY : E_FAIL;
179
180 /** @todo this is horribly inefficient! And it's kinda difficult to tell whether it failed...
181 * Must use UTF-8 or ASCII here and completely avoid these two extra copy operations.
182 * Until that's done, this method is kind of useless for debugger statistics GUI because
183 * of the amount statistics in a debug build. */
184 Bstr(pszSnapshot).cloneTo(aStats);
185
186 return S_OK;
187}
188
189/**
190 * Returns the current recompile user mode code flag.
191 *
192 * @returns COM status code
193 * @param enabled address of result variable
194 */
195STDMETHODIMP MachineDebugger::COMGETTER(RecompileUser)(BOOL *enabled)
196{
197 if (!enabled)
198 return E_POINTER;
199 AutoLock lock(this);
200 CHECK_READY();
201 Console::SafeVMPtrQuiet pVM (mParent);
202 if (pVM.isOk())
203 *enabled = !EMIsRawRing3Enabled(pVM.raw());
204 else
205 *enabled = false;
206 return S_OK;
207}
208
209/**
210 * Sets the recompile user mode code flag.
211 *
212 * @returns COM status
213 * @param enable new user mode code recompile flag.
214 */
215STDMETHODIMP MachineDebugger::COMSETTER(RecompileUser)(BOOL enable)
216{
217 LogFlowThisFunc (("enable=%d\n", enable));
218
219 AutoLock lock(this);
220 CHECK_READY();
221
222 if (!fFlushMode)
223 {
224 // check if the machine is running
225 MachineState_T machineState;
226 mParent->COMGETTER(State)(&machineState);
227 if (machineState != MachineState_Running)
228 {
229 // queue the request
230 recompileUserQueued = enable;
231 return S_OK;
232 }
233 }
234
235 Console::SafeVMPtr pVM (mParent);
236 CheckComRCReturnRC (pVM.rc());
237
238 PVMREQ pReq;
239 EMRAWMODE rawModeFlag = enable ? EMRAW_RING3_DISABLE : EMRAW_RING3_ENABLE;
240 int rcVBox = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT,
241 (PFNRT)EMR3RawSetMode, 2, pVM.raw(), rawModeFlag);
242 if (VBOX_SUCCESS(rcVBox))
243 {
244 rcVBox = pReq->iStatus;
245 VMR3ReqFree(pReq);
246 }
247
248 if (VBOX_SUCCESS(rcVBox))
249 return S_OK;
250
251 AssertMsgFailed(("Could not set raw mode flags to %d, rcVBox = %Vrc\n",
252 rawModeFlag, rcVBox));
253 return E_FAIL;
254}
255
256/**
257 * Returns the current recompile supervisor code flag.
258 *
259 * @returns COM status code
260 * @param enabled address of result variable
261 */
262STDMETHODIMP MachineDebugger::COMGETTER(RecompileSupervisor)(BOOL *enabled)
263{
264 if (!enabled)
265 return E_POINTER;
266 AutoLock lock(this);
267 CHECK_READY();
268 Console::SafeVMPtrQuiet pVM (mParent);
269 if (pVM.isOk())
270 *enabled = !EMIsRawRing0Enabled(pVM.raw());
271 else
272 *enabled = false;
273 return S_OK;
274}
275
276/**
277 * Sets the new recompile supervisor code flag.
278 *
279 * @returns COM status code
280 * @param enable new recompile supervisor code flag
281 */
282STDMETHODIMP MachineDebugger::COMSETTER(RecompileSupervisor)(BOOL enable)
283{
284 LogFlowThisFunc (("enable=%d\n", enable));
285
286 AutoLock lock(this);
287 CHECK_READY();
288
289 if (!fFlushMode)
290 {
291 // check if the machine is running
292 MachineState_T machineState;
293 mParent->COMGETTER(State)(&machineState);
294 if (machineState != MachineState_Running)
295 {
296 // queue the request
297 recompileSupervisorQueued = enable;
298 return S_OK;
299 }
300 }
301
302 Console::SafeVMPtr pVM (mParent);
303 CheckComRCReturnRC (pVM.rc());
304
305 PVMREQ pReq;
306 EMRAWMODE rawModeFlag = enable ? EMRAW_RING0_DISABLE : EMRAW_RING0_ENABLE;
307 int rcVBox = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT,
308 (PFNRT)EMR3RawSetMode, 2, pVM.raw(), rawModeFlag);
309 if (VBOX_SUCCESS(rcVBox))
310 {
311 rcVBox = pReq->iStatus;
312 VMR3ReqFree(pReq);
313 }
314
315 if (VBOX_SUCCESS(rcVBox))
316 return S_OK;
317
318 AssertMsgFailed(("Could not set raw mode flags to %d, rcVBox = %Vrc\n",
319 rawModeFlag, rcVBox));
320 return E_FAIL;
321}
322
323/**
324 * Returns the current patch manager enabled flag.
325 *
326 * @returns COM status code
327 * @param enabled address of result variable
328 */
329STDMETHODIMP MachineDebugger::COMGETTER(PATMEnabled)(BOOL *enabled)
330{
331 if (!enabled)
332 return E_POINTER;
333 AutoLock lock(this);
334 CHECK_READY();
335 Console::SafeVMPtrQuiet pVM (mParent);
336 if (pVM.isOk())
337 *enabled = PATMIsEnabled(pVM.raw());
338 else
339 *enabled = false;
340 return S_OK;
341}
342
343/**
344 * Set the new patch manager enabled flag.
345 *
346 * @returns COM status code
347 * @param new patch manager enabled flag
348 */
349STDMETHODIMP MachineDebugger::COMSETTER(PATMEnabled)(BOOL enable)
350{
351 AutoLock lock(this);
352 CHECK_READY();
353 LogFlowThisFunc (("enable=%d\n", enable));
354
355 if (!fFlushMode)
356 {
357 // check if the machine is running
358 MachineState_T machineState;
359 mParent->COMGETTER(State)(&machineState);
360 if (machineState != MachineState_Running)
361 {
362 // queue the request
363 patmEnabledQueued = enable;
364 return S_OK;
365 }
366 }
367
368 Console::SafeVMPtr pVM (mParent);
369 CheckComRCReturnRC (pVM.rc());
370
371 PATMR3AllowPatching(pVM, enable);
372 return E_NOTIMPL;
373}
374
375/**
376 * Returns the current code scanner enabled flag.
377 *
378 * @returns COM status code
379 * @param enabled address of result variable
380 */
381STDMETHODIMP MachineDebugger::COMGETTER(CSAMEnabled)(BOOL *enabled)
382{
383 if (!enabled)
384 return E_POINTER;
385 AutoLock lock(this);
386 CHECK_READY();
387 Console::SafeVMPtrQuiet pVM (mParent);
388 if (pVM.isOk())
389 *enabled = CSAMIsEnabled(pVM.raw());
390 else
391 *enabled = false;
392 return S_OK;
393}
394
395/**
396 * Sets the new code scanner enabled flag.
397 *
398 * @returns COM status code
399 * @param enable new code scanner enabled flag
400 */
401STDMETHODIMP MachineDebugger::COMSETTER(CSAMEnabled)(BOOL enable)
402{
403 AutoLock lock(this);
404 CHECK_READY();
405 LogFlowThisFunc (("enable=%d\n", enable));
406
407 if (!fFlushMode)
408 {
409 // check if the machine is running
410 MachineState_T machineState;
411 mParent->COMGETTER(State)(&machineState);
412 if (machineState != MachineState_Running)
413 {
414 // queue the request
415 csamEnabledQueued = enable;
416 return S_OK;
417 }
418 }
419
420 Console::SafeVMPtr pVM (mParent);
421 CheckComRCReturnRC (pVM.rc());
422
423 int vrc;
424 if (enable)
425 vrc = CSAMEnableScanning(pVM);
426 else
427 vrc = CSAMDisableScanning(pVM);
428 if (VBOX_FAILURE(vrc))
429 {
430 /** @todo handle error case */
431 }
432 return S_OK;
433}
434
435/**
436 * Returns the log enabled / disabled status.
437 *
438 * @returns COM status code
439 * @param aEnabled address of result variable
440 */
441STDMETHODIMP MachineDebugger::COMGETTER(LogEnabled)(BOOL *aEnabled)
442{
443 if (!aEnabled)
444 return E_POINTER;
445 AutoLock alock(this);
446 CHECK_READY();
447 PRTLOGGER pLogInstance = RTLogDefaultInstance();
448 *aEnabled = pLogInstance && !(pLogInstance->fFlags & RTLOGFLAGS_DISABLED);
449 return S_OK;
450}
451
452/**
453 * Enables or disables logging.
454 *
455 * @returns COM status code
456 * @param aEnabled The new code log state.
457 */
458STDMETHODIMP MachineDebugger::COMSETTER(LogEnabled)(BOOL aEnabled)
459{
460 AutoLock alock(this);
461
462 CHECK_READY();
463 LogFlowThisFunc (("aEnabled=%d\n", aEnabled));
464
465 if (!fFlushMode)
466 {
467 // check if the machine is running
468 MachineState_T machineState;
469 mParent->COMGETTER(State)(&machineState);
470 if (machineState != MachineState_Running)
471 {
472 // queue the request
473 mLogEnabledQueued = aEnabled;
474 return S_OK;
475 }
476 }
477
478 Console::SafeVMPtr pVM (mParent);
479 CheckComRCReturnRC (pVM.rc());
480
481 int vrc = DBGFR3LogModifyFlags(pVM, aEnabled ? "enabled" : "disabled");
482 if (VBOX_FAILURE(vrc))
483 {
484 /** @todo handle error code. */
485 }
486 return S_OK;
487}
488
489/**
490 * Returns the current hardware virtualization flag.
491 *
492 * @returns COM status code
493 * @param enabled address of result variable
494 */
495STDMETHODIMP MachineDebugger::COMGETTER(HWVirtExEnabled)(BOOL *enabled)
496{
497 if (!enabled)
498 return E_POINTER;
499
500 AutoLock lock(this);
501 CHECK_READY();
502
503 Console::SafeVMPtrQuiet pVM (mParent);
504 if (pVM.isOk())
505 *enabled = HWACCMIsEnabled(pVM.raw());
506 else
507 *enabled = false;
508 return S_OK;
509}
510
511/**
512 * Returns the current virtual time rate.
513 *
514 * @returns COM status code.
515 * @param pct Where to store the rate.
516 */
517STDMETHODIMP MachineDebugger::COMGETTER(VirtualTimeRate)(ULONG *pct)
518{
519 if (!pct)
520 return E_POINTER;
521
522 AutoLock lock(this);
523 CHECK_READY();
524
525 Console::SafeVMPtrQuiet pVM (mParent);
526 if (pVM.isOk())
527 *pct = TMVirtualGetWarpDrive(pVM);
528 else
529 *pct = 100;
530 return S_OK;
531}
532
533/**
534 * Returns the current virtual time rate.
535 *
536 * @returns COM status code.
537 * @param pct Where to store the rate.
538 */
539STDMETHODIMP MachineDebugger::COMSETTER(VirtualTimeRate)(ULONG pct)
540{
541 if (pct < 2 || pct > 20000)
542 return E_INVALIDARG;
543
544 AutoLock lock(this);
545 CHECK_READY();
546
547 if (!fFlushMode)
548 {
549 // check if the machine is running
550 MachineState_T machineState;
551 mParent->COMGETTER(State)(&machineState);
552 if (machineState != MachineState_Running)
553 {
554 // queue the request
555 mVirtualTimeRateQueued = pct;
556 return S_OK;
557 }
558 }
559
560 Console::SafeVMPtr pVM (mParent);
561 CheckComRCReturnRC (pVM.rc());
562
563 int vrc = TMVirtualSetWarpDrive(pVM, pct);
564 if (VBOX_FAILURE(vrc))
565 {
566 /** @todo handle error code. */
567 }
568 return S_OK;
569}
570
571/**
572 * Hack for getting the VM handle.
573 * This is only temporary (promise) while prototyping the debugger.
574 *
575 * @returns COM status code
576 * @param vm Where to store the vm handle.
577 * Since there is no uintptr_t in COM, we're using the max integer.
578 * (No, ULONG is not pointer sized!)
579 */
580STDMETHODIMP MachineDebugger::COMGETTER(VM)(ULONG64 *vm)
581{
582 if (!vm)
583 return E_POINTER;
584
585 AutoLock lock(this);
586 CHECK_READY();
587
588 Console::SafeVMPtr pVM (mParent);
589 CheckComRCReturnRC (pVM.rc());
590
591 *vm = (uintptr_t)pVM.raw();
592
593 /*
594 * Note: pVM protection provided by SafeVMPtr is no more effective
595 * after we return from this method.
596 */
597
598 return S_OK;
599}
600
601//
602// "public-private" methods
603//
604void MachineDebugger::flushQueuedSettings()
605{
606 fFlushMode = true;
607 if (singlestepQueued != ~0)
608 {
609 COMSETTER(Singlestep)(singlestepQueued);
610 singlestepQueued = ~0;
611 }
612 if (recompileUserQueued != ~0)
613 {
614 COMSETTER(RecompileUser)(recompileUserQueued);
615 recompileUserQueued = ~0;
616 }
617 if (recompileSupervisorQueued != ~0)
618 {
619 COMSETTER(RecompileSupervisor)(recompileSupervisorQueued);
620 recompileSupervisorQueued = ~0;
621 }
622 if (patmEnabledQueued != ~0)
623 {
624 COMSETTER(PATMEnabled)(patmEnabledQueued);
625 patmEnabledQueued = ~0;
626 }
627 if (csamEnabledQueued != ~0)
628 {
629 COMSETTER(CSAMEnabled)(csamEnabledQueued);
630 csamEnabledQueued = ~0;
631 }
632 if (mLogEnabledQueued != ~0)
633 {
634 COMSETTER(LogEnabled)(mLogEnabledQueued);
635 mLogEnabledQueued = ~0;
636 }
637 if (mVirtualTimeRateQueued != ~(uint32_t)0)
638 {
639 COMSETTER(VirtualTimeRate)(mVirtualTimeRateQueued);
640 mVirtualTimeRateQueued = ~0;
641 }
642 fFlushMode = false;
643}
644
645//
646// private methods
647//
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