VirtualBox

source: vbox/trunk/src/VBox/Debugger/VBoxDbgBase.cpp@ 86100

Last change on this file since 86100 was 85844, checked in by vboxsync, 4 years ago

Debugger: Don't crash with an UAF when closing the debugger console with ASAN enabled

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1/* $Id: VBoxDbgBase.cpp 85844 2020-08-20 13:14:20Z vboxsync $ */
2/** @file
3 * VBox Debugger GUI - Base classes.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGG
23#include <iprt/errcore.h>
24#include <iprt/asm.h>
25#include <iprt/assert.h>
26#include <limits.h>
27#include "VBoxDbgBase.h"
28#include "VBoxDbgGui.h"
29
30#include <QApplication>
31#include <QWidgetList>
32
33
34
35VBoxDbgBase::VBoxDbgBase(VBoxDbgGui *a_pDbgGui)
36 : m_pDbgGui(a_pDbgGui), m_pUVM(NULL), m_hGUIThread(RTThreadNativeSelf())
37{
38 NOREF(m_pDbgGui); /* shut up warning. */
39
40 /*
41 * Register
42 */
43 m_pUVM = a_pDbgGui->getUvmHandle();
44 if (m_pUVM)
45 {
46 VMR3RetainUVM(m_pUVM);
47
48 int rc = VMR3AtStateRegister(m_pUVM, atStateChange, this);
49 AssertRC(rc);
50 }
51}
52
53
54VBoxDbgBase::~VBoxDbgBase()
55{
56 /*
57 * If the VM is still around.
58 */
59 /** @todo need to do some locking here? */
60 PUVM pUVM = ASMAtomicXchgPtrT(&m_pUVM, NULL, PUVM);
61 if (pUVM)
62 {
63 int rc = VMR3AtStateDeregister(pUVM, atStateChange, this);
64 AssertRC(rc);
65
66 VMR3ReleaseUVM(pUVM);
67 }
68}
69
70
71int
72VBoxDbgBase::stamReset(const QString &rPat)
73{
74 QByteArray Utf8Array = rPat.toUtf8();
75 const char *pszPat = !rPat.isEmpty() ? Utf8Array.constData() : NULL;
76 PUVM pUVM = m_pUVM;
77 if ( pUVM
78 && VMR3GetStateU(pUVM) < VMSTATE_DESTROYING)
79 return STAMR3Reset(pUVM, pszPat);
80 return VERR_INVALID_HANDLE;
81}
82
83
84int
85VBoxDbgBase::stamEnum(const QString &rPat, PFNSTAMR3ENUM pfnEnum, void *pvUser)
86{
87 QByteArray Utf8Array = rPat.toUtf8();
88 const char *pszPat = !rPat.isEmpty() ? Utf8Array.constData() : NULL;
89 PUVM pUVM = m_pUVM;
90 if ( pUVM
91 && VMR3GetStateU(pUVM) < VMSTATE_DESTROYING)
92 return STAMR3Enum(pUVM, pszPat, pfnEnum, pvUser);
93 return VERR_INVALID_HANDLE;
94}
95
96
97int
98VBoxDbgBase::dbgcCreate(PDBGCBACK pBack, unsigned fFlags)
99{
100 PUVM pUVM = m_pUVM;
101 if ( pUVM
102 && VMR3GetStateU(pUVM) < VMSTATE_DESTROYING)
103 return DBGCCreate(pUVM, pBack, fFlags);
104 return VERR_INVALID_HANDLE;
105}
106
107
108/*static*/ DECLCALLBACK(void)
109VBoxDbgBase::atStateChange(PUVM pUVM, VMSTATE enmState, VMSTATE /*enmOldState*/, void *pvUser)
110{
111 VBoxDbgBase *pThis = (VBoxDbgBase *)pvUser; NOREF(pUVM);
112 switch (enmState)
113 {
114 case VMSTATE_TERMINATED:
115 {
116 /** @todo need to do some locking here? */
117 PUVM pUVM2 = ASMAtomicXchgPtrT(&pThis->m_pUVM, NULL, PUVM);
118 if (pUVM2)
119 {
120 Assert(pUVM2 == pUVM);
121 pThis->sigTerminated();
122 VMR3ReleaseUVM(pUVM2);
123 }
124 break;
125 }
126
127 case VMSTATE_DESTROYING:
128 pThis->sigDestroying();
129 break;
130
131 default:
132 break;
133 }
134}
135
136
137void
138VBoxDbgBase::sigDestroying()
139{
140}
141
142
143void
144VBoxDbgBase::sigTerminated()
145{
146}
147
148
149
150
151//
152//
153//
154// V B o x D b g B a s e W i n d o w
155// V B o x D b g B a s e W i n d o w
156// V B o x D b g B a s e W i n d o w
157//
158//
159//
160
161unsigned VBoxDbgBaseWindow::m_cxBorder = 0;
162unsigned VBoxDbgBaseWindow::m_cyBorder = 0;
163
164
165VBoxDbgBaseWindow::VBoxDbgBaseWindow(VBoxDbgGui *a_pDbgGui, QWidget *a_pParent, const char *a_pszTitle)
166 : QWidget(a_pParent, Qt::Window), VBoxDbgBase(a_pDbgGui), m_pszTitle(a_pszTitle), m_fPolished(false)
167 , m_x(INT_MAX), m_y(INT_MAX), m_cx(0), m_cy(0)
168{
169 /* Set the title, using the parent one as prefix when possible: */
170 if (!parent())
171 {
172 QString strMachineName = a_pDbgGui->getMachineName();
173 if (strMachineName.isEmpty())
174 setWindowTitle(QString("VBoxDbg - %1").arg(m_pszTitle));
175 else
176 setWindowTitle(QString("%1 - VBoxDbg - %2").arg(strMachineName).arg(m_pszTitle));
177 }
178 else
179 {
180 setWindowTitle(QString("%1 - %2").arg(parentWidget()->windowTitle()).arg(m_pszTitle));
181
182 /* Install an event filter so we can make adjustments when the parent title changes: */
183 parent()->installEventFilter(this);
184 }
185}
186
187
188VBoxDbgBaseWindow::~VBoxDbgBaseWindow()
189{
190
191}
192
193
194void
195VBoxDbgBaseWindow::vShow()
196{
197 show();
198 /** @todo this ain't working right. HELP! */
199 setWindowState(windowState() & ~Qt::WindowMinimized);
200 //activateWindow();
201 //setFocus();
202 vPolishSizeAndPos();
203}
204
205
206void
207VBoxDbgBaseWindow::vReposition(int a_x, int a_y, unsigned a_cx, unsigned a_cy, bool a_fResize)
208{
209 if (a_fResize)
210 {
211 m_cx = a_cx;
212 m_cy = a_cy;
213
214 QSize BorderSize = frameSize() - size();
215 if (BorderSize == QSize(0,0))
216 BorderSize = vGuessBorderSizes();
217
218 resize(a_cx - BorderSize.width(), a_cy - BorderSize.height());
219 }
220
221 m_x = a_x;
222 m_y = a_y;
223 move(a_x, a_y);
224}
225
226
227bool
228VBoxDbgBaseWindow::event(QEvent *a_pEvt)
229{
230 bool fRc = QWidget::event(a_pEvt);
231 if ( a_pEvt->type() == QEvent::Paint
232 || a_pEvt->type() == QEvent::UpdateRequest
233 || a_pEvt->type() == QEvent::LayoutRequest) /** @todo Someone with Qt knowledge should figure out how to properly do this. */
234 vPolishSizeAndPos();
235 return fRc;
236}
237
238
239bool VBoxDbgBaseWindow::eventFilter(QObject *pWatched, QEvent *pEvent)
240{
241 /* We're only interested in title changes to the parent so we can amend our own title: */
242 if ( pWatched == parent()
243 && pEvent->type() == QEvent::WindowTitleChange)
244 setWindowTitle(QString("%1 - %2").arg(parentWidget()->windowTitle()).arg(m_pszTitle));
245
246 /* Forward to base-class: */
247 return QWidget::eventFilter(pWatched, pEvent);
248}
249
250
251void
252VBoxDbgBaseWindow::vPolishSizeAndPos()
253{
254 /* Ignore if already done or no size set. */
255 if ( m_fPolished
256 || (m_x == INT_MAX && m_y == INT_MAX))
257 return;
258
259 QSize BorderSize = frameSize() - size();
260 if (BorderSize != QSize(0,0))
261 m_fPolished = true;
262
263 vReposition(m_x, m_y, m_cx, m_cy, m_cx || m_cy);
264}
265
266
267QSize
268VBoxDbgBaseWindow::vGuessBorderSizes()
269{
270#ifdef Q_WS_X11 /* (from the qt gui) */
271 /*
272 * On X11, there is no way to determine frame geometry (including WM
273 * decorations) before the widget is shown for the first time. Stupidly
274 * enumerate other top level widgets to find the thickest frame.
275 */
276 if (!m_cxBorder && !m_cyBorder) /* (only till we're successful) */
277 {
278 int cxExtra = 0;
279 int cyExtra = 0;
280
281 QWidgetList WidgetList = QApplication::topLevelWidgets();
282 for (QListIterator<QWidget *> it(WidgetList); it.hasNext(); )
283 {
284 QWidget *pCurWidget = it.next();
285 if (pCurWidget->isVisible())
286 {
287 int const cxFrame = pCurWidget->frameGeometry().width() - pCurWidget->width();
288 cxExtra = qMax(cxExtra, cxFrame);
289 int const cyFrame = pCurWidget->frameGeometry().height() - pCurWidget->height();
290 cyExtra = qMax(cyExtra, cyFrame);
291 if (cyExtra && cxExtra)
292 break;
293 }
294 }
295
296 if (cxExtra || cyExtra)
297 {
298 m_cxBorder = cxExtra;
299 m_cyBorder = cyExtra;
300 }
301 }
302#endif /* X11 */
303 return QSize(m_cxBorder, m_cyBorder);
304}
305
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