VirtualBox

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

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