VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/GuestDebugControlImpl.cpp

Last change on this file was 106061, checked in by vboxsync, 8 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.5 KB
Line 
1/* $Id: GuestDebugControlImpl.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VirtualBox/GuestDebugControl COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_MAIN_GUESTDEBUGCONTROL
29#include "GuestDebugControlImpl.h"
30#include "MachineImpl.h"
31#include "VirtualBoxImpl.h"
32#include "GuestOSTypeImpl.h"
33
34#include <iprt/assert.h>
35#include <iprt/string.h>
36#include <iprt/cpp/utils.h>
37
38#include <VBox/settings.h>
39
40#include "AutoStateDep.h"
41#include "AutoCaller.h"
42#include "LoggingNew.h"
43
44//////////////////////////////////////////////////////////////////////////////////
45//
46// GuestDebugControl private data definition
47//
48//////////////////////////////////////////////////////////////////////////////////
49
50struct GuestDebugControl::Data
51{
52 Data()
53 : pMachine(NULL)
54 { }
55
56 Machine * const pMachine;
57 const ComObjPtr<GuestDebugControl> pPeer;
58 Backupable<settings::Debugging> bd;
59};
60
61// constructor / destructor
62/////////////////////////////////////////////////////////////////////////////
63
64DEFINE_EMPTY_CTOR_DTOR(GuestDebugControl)
65
66HRESULT GuestDebugControl::FinalConstruct()
67{
68 return BaseFinalConstruct();
69}
70
71void GuestDebugControl::FinalRelease()
72{
73 uninit();
74 BaseFinalRelease();
75}
76
77// public initializer/uninitializer for internal purposes only
78/////////////////////////////////////////////////////////////////////////////
79
80/**
81 * Initializes the Guest Debug Control object.
82 *
83 * @param aParent Handle of the parent object.
84 */
85HRESULT GuestDebugControl::init(Machine *aParent)
86{
87 LogFlowThisFunc(("aParent=%p\n", aParent));
88
89 ComAssertRet(aParent, E_INVALIDARG);
90
91 /* Enclose the state transition NotReady->InInit->Ready */
92 AutoInitSpan autoInitSpan(this);
93 AssertReturn(autoInitSpan.isOk(), E_FAIL);
94
95 m = new Data();
96
97 unconst(m->pMachine) = aParent;
98 /* m->pPeer is left null */
99
100 m->bd.allocate();
101
102 /* Confirm a successful initialization */
103 autoInitSpan.setSucceeded();
104
105 return S_OK;
106}
107
108/**
109 * Initializes the Guest Debug Control object given another Guest Debug Control object
110 * (a kind of copy constructor). This object shares data with
111 * the object passed as an argument.
112 *
113 * @note This object must be destroyed before the original object
114 * it shares data with is destroyed.
115 *
116 * @note Locks @a aThat object for reading.
117 */
118HRESULT GuestDebugControl::init(Machine *aParent, GuestDebugControl *aThat)
119{
120 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
121
122 ComAssertRet(aParent && aThat, E_INVALIDARG);
123
124 /* Enclose the state transition NotReady->InInit->Ready */
125 AutoInitSpan autoInitSpan(this);
126 AssertReturn(autoInitSpan.isOk(), E_FAIL);
127
128 m = new Data();
129
130 unconst(m->pMachine) = aParent;
131 unconst(m->pPeer) = aThat;
132
133 AutoCaller thatCaller(aThat);
134 AssertComRCReturnRC(thatCaller.hrc());
135
136 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
137 m->bd.share(aThat->m->bd);
138
139 /* Confirm a successful initialization */
140 autoInitSpan.setSucceeded();
141
142 return S_OK;
143}
144
145/**
146 * Initializes the guest object given another guest object
147 * (a kind of copy constructor). This object makes a private copy of data
148 * of the original object passed as an argument.
149 *
150 * @note Locks @a aThat object for reading.
151 */
152HRESULT GuestDebugControl::initCopy(Machine *aParent, GuestDebugControl *aThat)
153{
154 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
155
156 ComAssertRet(aParent && aThat, E_INVALIDARG);
157
158 /* Enclose the state transition NotReady->InInit->Ready */
159 AutoInitSpan autoInitSpan(this);
160 AssertReturn(autoInitSpan.isOk(), E_FAIL);
161
162 m = new Data();
163
164 unconst(m->pMachine) = aParent;
165 /* pPeer is left null */
166
167 AutoCaller thatCaller(aThat);
168 AssertComRCReturnRC(thatCaller.hrc());
169
170 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
171 m->bd.attachCopy(aThat->m->bd);
172
173 /* Confirm a successful initialization */
174 autoInitSpan.setSucceeded();
175
176 return S_OK;
177}
178
179/**
180 * Uninitializes the instance and sets the ready flag to FALSE.
181 * Called either from FinalRelease() or by the parent when it gets destroyed.
182 */
183void GuestDebugControl::uninit()
184{
185 LogFlowThisFunc(("\n"));
186
187 /* Enclose the state transition Ready->InUninit->NotReady */
188 AutoUninitSpan autoUninitSpan(this);
189 if (autoUninitSpan.uninitDone())
190 return;
191
192 m->bd.free();
193
194 unconst(m->pPeer) = NULL;
195 unconst(m->pMachine) = NULL;
196
197 delete m;
198 m = NULL;
199}
200
201// IGuestDebugControl properties
202/////////////////////////////////////////////////////////////////////////////
203
204HRESULT GuestDebugControl::getDebugProvider(GuestDebugProvider_T *aDebugProvider)
205{
206 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
207
208 *aDebugProvider = m->bd->enmDbgProvider;
209 return S_OK;
210}
211
212
213HRESULT GuestDebugControl::setDebugProvider(GuestDebugProvider_T aDebugProvider)
214{
215 /* the machine needs to be mutable */
216 AutoMutableOrSavedOrRunningStateDependency adep(m->pMachine);
217 if (FAILED(adep.hrc())) return adep.hrc();
218
219 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
220
221 if (m->bd->enmDbgProvider != aDebugProvider)
222 {
223 m->bd.backup();
224 m->bd->enmDbgProvider = aDebugProvider;
225
226 // leave the lock before informing callbacks
227 alock.release();
228
229 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
230 m->pMachine->i_setModified(Machine::IsModified_GuestDebugControl);
231 mlock.release();
232
233 m->pMachine->i_onGuestDebugControlChange(this);
234 }
235
236 return S_OK;
237}
238
239
240HRESULT GuestDebugControl::getDebugIoProvider(GuestDebugIoProvider_T *aDebugIoProvider)
241{
242 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
243
244 *aDebugIoProvider = m->bd->enmIoProvider;
245 return S_OK;
246}
247
248HRESULT GuestDebugControl::setDebugIoProvider(GuestDebugIoProvider_T aDebugIoProvider)
249{
250 /* the machine needs to be mutable */
251 AutoMutableOrSavedOrRunningStateDependency adep(m->pMachine);
252 if (FAILED(adep.hrc())) return adep.hrc();
253
254 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
255
256 if (m->bd->enmIoProvider != aDebugIoProvider)
257 {
258 m->bd.backup();
259 m->bd->enmIoProvider = aDebugIoProvider;
260
261 // leave the lock before informing callbacks
262 alock.release();
263
264 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
265 m->pMachine->i_setModified(Machine::IsModified_GuestDebugControl);
266 mlock.release();
267
268 m->pMachine->i_onGuestDebugControlChange(this);
269 }
270
271 return S_OK;
272}
273
274HRESULT GuestDebugControl::getDebugAddress(com::Utf8Str &aAddress)
275{
276 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
277
278 aAddress = m->bd->strAddress;
279
280 return S_OK;
281}
282
283
284HRESULT GuestDebugControl::setDebugAddress(const com::Utf8Str &aAddress)
285{
286 /* the machine needs to be mutable */
287 AutoMutableOrSavedOrRunningStateDependency adep(m->pMachine);
288 if (FAILED(adep.hrc())) return adep.hrc();
289
290 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
291
292 if (aAddress != m->bd->strAddress)
293 {
294 m->bd.backup();
295 m->bd->strAddress = aAddress;
296
297 // leave the lock before informing callbacks
298 alock.release();
299
300 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
301 m->pMachine->i_setModified(Machine::IsModified_GuestDebugControl);
302 mlock.release();
303
304 m->pMachine->i_onGuestDebugControlChange(this);
305 }
306
307 return S_OK;
308}
309
310HRESULT GuestDebugControl::getDebugPort(ULONG *aPort)
311{
312 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
313
314 *aPort = m->bd->ulPort;
315 return S_OK;
316}
317
318HRESULT GuestDebugControl::setDebugPort(ULONG aPort)
319{
320 /* the machine needs to be mutable */
321 AutoMutableOrSavedOrRunningStateDependency adep(m->pMachine);
322 if (FAILED(adep.hrc())) return adep.hrc();
323
324 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
325
326 if (m->bd->ulPort != aPort)
327 {
328 m->bd.backup();
329 m->bd->ulPort = aPort;
330
331 // leave the lock before informing callbacks
332 alock.release();
333
334 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
335 m->pMachine->i_setModified(Machine::IsModified_GuestDebugControl);
336 mlock.release();
337
338 m->pMachine->i_onGuestDebugControlChange(this);
339 }
340
341 return S_OK;
342}
343
344// public methods only for internal purposes
345////////////////////////////////////////////////////////////////////////////////
346
347/**
348 * Loads debug settings from the given settings.
349 * May be called once right after this object creation.
350 *
351 * @param data Configuration settings.
352 *
353 * @note Locks this object for writing.
354 */
355HRESULT GuestDebugControl::i_loadSettings(const settings::Debugging &data)
356{
357
358 AutoCaller autoCaller(this);
359 AssertComRCReturnRC(autoCaller.hrc());
360
361 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
362
363 // simply copy
364 *m->bd.data() = data;
365
366 return S_OK;
367}
368
369/**
370 * Saves the debug settings to the given settings.
371 *
372 * Note that the given Port node is completely empty on input.
373 *
374 * @param data Configuration settings.
375 *
376 * @note Locks this object for reading.
377 */
378HRESULT GuestDebugControl::i_saveSettings(settings::Debugging &data)
379{
380 AutoCaller autoCaller(this);
381 AssertComRCReturnRC(autoCaller.hrc());
382
383 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
384
385 // simply copy
386 data = *m->bd.data();
387
388 return S_OK;
389}
390
391/**
392 * @note Locks this object for writing.
393 */
394void GuestDebugControl::i_rollback()
395{
396 /* sanity */
397 AutoCaller autoCaller(this);
398 AssertComRCReturnVoid(autoCaller.hrc());
399
400 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
401
402 m->bd.rollback();
403}
404
405/**
406 * @note Locks this object for writing, together with the peer object (also
407 * for writing) if there is one.
408 */
409void GuestDebugControl::i_commit()
410{
411 /* sanity */
412 AutoCaller autoCaller(this);
413 AssertComRCReturnVoid(autoCaller.hrc());
414
415 /* sanity too */
416 AutoCaller peerCaller(m->pPeer);
417 AssertComRCReturnVoid(peerCaller.hrc());
418
419 /* lock both for writing since we modify both (pPeer is "master" so locked
420 * first) */
421 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
422
423 if (m->bd.isBackedUp())
424 {
425 m->bd.commit();
426 if (m->pPeer)
427 {
428 /* attach new data to the peer and reshare it */
429 m->pPeer->m->bd.attach(m->bd);
430 }
431 }
432}
433
434/**
435 * @note Locks this object for writing, together with the peer object
436 * represented by @a aThat (locked for reading).
437 */
438void GuestDebugControl::i_copyFrom(GuestDebugControl *aThat)
439{
440 AssertReturnVoid(aThat != NULL);
441
442 /* sanity */
443 AutoCaller autoCaller(this);
444 AssertComRCReturnVoid(autoCaller.hrc());
445
446 /* sanity too */
447 AutoCaller thatCaller(aThat);
448 AssertComRCReturnVoid(thatCaller.hrc());
449
450 /* peer is not modified, lock it for reading (aThat is "master" so locked
451 * first) */
452 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
453 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
454
455 /* this will back up current data */
456 m->bd.assignCopy(aThat->m->bd);
457}
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