VirtualBox

source: vbox/trunk/src/VBox/VMM/include/DBGFInternal.h@ 78003

Last change on this file since 78003 was 76585, checked in by vboxsync, 6 years ago

*: scm --fix-header-guard-endif

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 18.2 KB
Line 
1/* $Id: DBGFInternal.h 76585 2019-01-01 06:31:29Z vboxsync $ */
2/** @file
3 * DBGF - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2019 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#ifndef VMM_INCLUDED_SRC_include_DBGFInternal_h
19#define VMM_INCLUDED_SRC_include_DBGFInternal_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24#include <VBox/cdefs.h>
25#ifdef IN_RING3
26# include <VBox/dis.h>
27#endif
28#include <VBox/types.h>
29#include <iprt/semaphore.h>
30#include <iprt/critsect.h>
31#include <iprt/string.h>
32#include <iprt/avl.h>
33#include <iprt/dbg.h>
34#include <VBox/vmm/dbgf.h>
35
36
37
38/** @defgroup grp_dbgf_int Internals
39 * @ingroup grp_dbgf
40 * @internal
41 * @{
42 */
43
44
45/** VMM Debugger Command. */
46typedef enum DBGFCMD
47{
48 /** No command.
49 * This is assigned to the field by the emulation thread after
50 * a command has been completed. */
51 DBGFCMD_NO_COMMAND = 0,
52 /** Halt the VM. */
53 DBGFCMD_HALT,
54 /** Resume execution. */
55 DBGFCMD_GO,
56 /** Single step execution - stepping into calls. */
57 DBGFCMD_SINGLE_STEP,
58 /** Detaches the debugger.
59 * Disabling all breakpoints, watch points and the like. */
60 DBGFCMD_DETACH_DEBUGGER,
61 /** Detached the debugger.
62 * The isn't a command as such, it's just that it's necessary for the
63 * detaching protocol to be racefree. */
64 DBGFCMD_DETACHED_DEBUGGER
65} DBGFCMD;
66
67/**
68 * VMM Debugger Command.
69 */
70typedef union DBGFCMDDATA
71{
72 uint32_t uDummy;
73} DBGFCMDDATA;
74/** Pointer to DBGF Command Data. */
75typedef DBGFCMDDATA *PDBGFCMDDATA;
76
77/**
78 * Info type.
79 */
80typedef enum DBGFINFOTYPE
81{
82 /** Invalid. */
83 DBGFINFOTYPE_INVALID = 0,
84 /** Device owner. */
85 DBGFINFOTYPE_DEV,
86 /** Driver owner. */
87 DBGFINFOTYPE_DRV,
88 /** Internal owner. */
89 DBGFINFOTYPE_INT,
90 /** External owner. */
91 DBGFINFOTYPE_EXT
92} DBGFINFOTYPE;
93
94
95/** Pointer to info structure. */
96typedef struct DBGFINFO *PDBGFINFO;
97
98#ifdef IN_RING3
99/**
100 * Info structure.
101 */
102typedef struct DBGFINFO
103{
104 /** The flags. */
105 uint32_t fFlags;
106 /** Owner type. */
107 DBGFINFOTYPE enmType;
108 /** Per type data. */
109 union
110 {
111 /** DBGFINFOTYPE_DEV */
112 struct
113 {
114 /** Device info handler function. */
115 PFNDBGFHANDLERDEV pfnHandler;
116 /** The device instance. */
117 PPDMDEVINS pDevIns;
118 } Dev;
119
120 /** DBGFINFOTYPE_DRV */
121 struct
122 {
123 /** Driver info handler function. */
124 PFNDBGFHANDLERDRV pfnHandler;
125 /** The driver instance. */
126 PPDMDRVINS pDrvIns;
127 } Drv;
128
129 /** DBGFINFOTYPE_INT */
130 struct
131 {
132 /** Internal info handler function. */
133 PFNDBGFHANDLERINT pfnHandler;
134 } Int;
135
136 /** DBGFINFOTYPE_EXT */
137 struct
138 {
139 /** External info handler function. */
140 PFNDBGFHANDLEREXT pfnHandler;
141 /** The user argument. */
142 void *pvUser;
143 } Ext;
144 } u;
145
146 /** Pointer to the description. */
147 const char *pszDesc;
148 /** Pointer to the next info structure. */
149 PDBGFINFO pNext;
150 /** The identifier name length. */
151 size_t cchName;
152 /** The identifier name. (Extends 'beyond' the struct as usual.) */
153 char szName[1];
154} DBGFINFO;
155#endif /* IN_RING3 */
156
157
158#ifdef IN_RING3
159/**
160 * Guest OS digger instance.
161 */
162typedef struct DBGFOS
163{
164 /** Pointer to the registration record. */
165 PCDBGFOSREG pReg;
166 /** Pointer to the next OS we've registered. */
167 struct DBGFOS *pNext;
168 /** List of EMT interface wrappers. */
169 struct DBGFOSEMTWRAPPER *pWrapperHead;
170 /** The instance data (variable size). */
171 uint8_t abData[16];
172} DBGFOS;
173#endif
174/** Pointer to guest OS digger instance. */
175typedef struct DBGFOS *PDBGFOS;
176/** Pointer to const guest OS digger instance. */
177typedef struct DBGFOS const *PCDBGFOS;
178
179
180/**
181 * Breakpoint search optimization.
182 */
183typedef struct DBGFBPSEARCHOPT
184{
185 /** Where to start searching for hits.
186 * (First enabled is #DBGF::aBreakpoints[iStartSearch]). */
187 uint32_t volatile iStartSearch;
188 /** The number of aBreakpoints entries to search.
189 * (Last enabled is #DBGF::aBreakpoints[iStartSearch + cToSearch - 1]) */
190 uint32_t volatile cToSearch;
191} DBGFBPSEARCHOPT;
192/** Pointer to a breakpoint search optimziation structure. */
193typedef DBGFBPSEARCHOPT *PDBGFBPSEARCHOPT;
194
195
196
197/**
198 * DBGF Data (part of VM)
199 */
200typedef struct DBGF
201{
202 /** Bitmap of enabled hardware interrupt breakpoints. */
203 uint32_t bmHardIntBreakpoints[256 / 32];
204 /** Bitmap of enabled software interrupt breakpoints. */
205 uint32_t bmSoftIntBreakpoints[256 / 32];
206 /** Bitmap of selected events.
207 * This includes non-selectable events too for simplicity, we maintain the
208 * state for some of these, as it may come in handy. */
209 uint64_t bmSelectedEvents[(DBGFEVENT_END + 63) / 64];
210
211 /** Enabled hardware interrupt breakpoints. */
212 uint32_t cHardIntBreakpoints;
213 /** Enabled software interrupt breakpoints. */
214 uint32_t cSoftIntBreakpoints;
215
216 /** The number of selected events. */
217 uint32_t cSelectedEvents;
218
219 /** The number of enabled hardware breakpoints. */
220 uint8_t cEnabledHwBreakpoints;
221 /** The number of enabled hardware I/O breakpoints. */
222 uint8_t cEnabledHwIoBreakpoints;
223 /** The number of enabled INT3 breakpoints. */
224 uint8_t cEnabledInt3Breakpoints;
225 uint8_t abPadding; /**< Unused padding space up for grabs. */
226 uint32_t uPadding;
227
228 /** Debugger Attached flag.
229 * Set if a debugger is attached, elsewise it's clear.
230 */
231 bool volatile fAttached;
232
233 /** Stopped in the Hypervisor.
234 * Set if we're stopped on a trace, breakpoint or assertion inside
235 * the hypervisor and have to restrict the available operations.
236 */
237 bool volatile fStoppedInHyper;
238
239 /**
240 * Ping-Pong construct where the Ping side is the VMM and the Pong side
241 * the Debugger.
242 */
243 RTPINGPONG PingPong;
244 RTHCUINTPTR uPtrPadding; /**< Alignment padding. */
245
246 /** The Event to the debugger.
247 * The VMM will ping the debugger when the event is ready. The event is
248 * either a response to a command or to a break/watch point issued
249 * previously.
250 */
251 DBGFEVENT DbgEvent;
252
253 /** The Command to the VMM.
254 * Operated in an atomic fashion since the VMM will poll on this.
255 * This means that a the command data must be written before this member
256 * is set. The VMM will reset this member to the no-command state
257 * when it have processed it.
258 */
259 DBGFCMD volatile enmVMMCmd;
260 /** The Command data.
261 * Not all commands take data. */
262 DBGFCMDDATA VMMCmdData;
263
264 /** Stepping filtering. */
265 struct
266 {
267 /** The CPU doing the stepping.
268 * Set to NIL_VMCPUID when filtering is inactive */
269 VMCPUID idCpu;
270 /** The specified flags. */
271 uint32_t fFlags;
272 /** The effective PC address to stop at, if given. */
273 RTGCPTR AddrPc;
274 /** The lowest effective stack address to stop at.
275 * Together with cbStackPop, this forms a range of effective stack pointer
276 * addresses that we stop for. */
277 RTGCPTR AddrStackPop;
278 /** The size of the stack stop area starting at AddrStackPop. */
279 RTGCPTR cbStackPop;
280 /** Maximum number of steps. */
281 uint32_t cMaxSteps;
282
283 /** Number of steps made thus far. */
284 uint32_t cSteps;
285 /** Current call counting balance for step-over handling. */
286 uint32_t uCallDepth;
287
288 uint32_t u32Padding; /**< Alignment padding. */
289
290 } SteppingFilter;
291
292 uint32_t u32Padding[2]; /**< Alignment padding. */
293
294 /** Array of hardware breakpoints. (0..3)
295 * This is shared among all the CPUs because life is much simpler that way. */
296 DBGFBP aHwBreakpoints[4];
297 /** Array of int 3 and REM breakpoints. (4..)
298 * @remark This is currently a fixed size array for reasons of simplicity. */
299 DBGFBP aBreakpoints[32];
300
301 /** MMIO breakpoint search optimizations. */
302 DBGFBPSEARCHOPT Mmio;
303 /** I/O port breakpoint search optimizations. */
304 DBGFBPSEARCHOPT PortIo;
305 /** INT3 breakpoint search optimizations. */
306 DBGFBPSEARCHOPT Int3;
307
308 /**
309 * Bug check data.
310 * @note This will not be reset on reset.
311 */
312 struct
313 {
314 /** The ID of the CPU reporting it. */
315 VMCPUID idCpu;
316 /** The event associated with the bug check (gives source).
317 * This is set to DBGFEVENT_END if no BSOD data here. */
318 DBGFEVENTTYPE enmEvent;
319 /** The total reset count at the time (VMGetResetCount). */
320 uint32_t uResetNo;
321 /** Explicit padding. */
322 uint32_t uPadding;
323 /** When it was reported (TMVirtualGet). */
324 uint64_t uTimestamp;
325 /** The bug check number.
326 * @note This is really just 32-bit wide, see KeBugCheckEx. */
327 uint64_t uBugCheck;
328 /** The bug check parameters. */
329 uint64_t auParameters[4];
330 } BugCheck;
331} DBGF;
332AssertCompileMemberAlignment(DBGF, DbgEvent, 8);
333AssertCompileMemberAlignment(DBGF, aHwBreakpoints, 8);
334AssertCompileMemberAlignment(DBGF, bmHardIntBreakpoints, 8);
335/** Pointer to DBGF Data. */
336typedef DBGF *PDBGF;
337
338
339/**
340 * Event state (for DBGFCPU::aEvents).
341 */
342typedef enum DBGFEVENTSTATE
343{
344 /** Invalid event stack entry. */
345 DBGFEVENTSTATE_INVALID = 0,
346 /** The current event stack entry. */
347 DBGFEVENTSTATE_CURRENT,
348 /** Event that should be ignored but hasn't yet actually been ignored. */
349 DBGFEVENTSTATE_IGNORE,
350 /** Event that has been ignored but may be restored to IGNORE should another
351 * debug event fire before the instruction is completed. */
352 DBGFEVENTSTATE_RESTORABLE,
353 /** End of valid events. */
354 DBGFEVENTSTATE_END,
355 /** Make sure we've got a 32-bit type. */
356 DBGFEVENTSTATE_32BIT_HACK = 0x7fffffff
357} DBGFEVENTSTATE;
358
359
360/** Converts a DBGFCPU pointer into a VM pointer. */
361#define DBGFCPU_2_VM(pDbgfCpu) ((PVM)((uint8_t *)(pDbgfCpu) + (pDbgfCpu)->offVM))
362
363/**
364 * The per CPU data for DBGF.
365 */
366typedef struct DBGFCPU
367{
368 /** The offset into the VM structure.
369 * @see DBGFCPU_2_VM(). */
370 uint32_t offVM;
371
372 /** Current active breakpoint (id).
373 * This is ~0U if not active. It is set when a execution engine
374 * encounters a breakpoint and returns VINF_EM_DBG_BREAKPOINT. This is
375 * currently not used for REM breakpoints because of the lazy coupling
376 * between VBox and REM.
377 *
378 * @todo drop this in favor of aEvents! */
379 uint32_t iActiveBp;
380 /** Set if we're singlestepping in raw mode.
381 * This is checked and cleared in the \#DB handler. */
382 bool fSingleSteppingRaw;
383
384 /** Alignment padding. */
385 bool afPadding[3];
386
387 /** The number of events on the stack (aEvents).
388 * The pending event is the last one (aEvents[cEvents - 1]), but only when
389 * enmState is DBGFEVENTSTATE_CURRENT. */
390 uint32_t cEvents;
391 /** Events - current, ignoring and ignored.
392 *
393 * We maintain a stack of events in order to try avoid ending up in an infinit
394 * loop when resuming after an event fired. There are cases where we may end
395 * generating additional events before the instruction can be executed
396 * successfully. Like for instance an XCHG on MMIO with separate read and write
397 * breakpoints, or a MOVSB instruction working on breakpointed MMIO as both
398 * source and destination.
399 *
400 * So, when resuming after dropping into the debugger for an event, we convert
401 * the DBGFEVENTSTATE_CURRENT event into a DBGFEVENTSTATE_IGNORE event, leaving
402 * cEvents unchanged. If the event is reported again, we will ignore it and
403 * tell the reporter to continue executing. The event change to the
404 * DBGFEVENTSTATE_RESTORABLE state.
405 *
406 * Currently, the event reporter has to figure out that it is a nested event and
407 * tell DBGF to restore DBGFEVENTSTATE_RESTORABLE events (and keep
408 * DBGFEVENTSTATE_IGNORE, should they happen out of order for some weird
409 * reason).
410 */
411 struct
412 {
413 /** The event details. */
414 DBGFEVENT Event;
415 /** The RIP at which this happend (for validating ignoring). */
416 uint64_t rip;
417 /** The event state. */
418 DBGFEVENTSTATE enmState;
419 /** Alignment padding. */
420 uint32_t u32Alignment;
421 } aEvents[3];
422} DBGFCPU;
423AssertCompileMemberAlignment(DBGFCPU, aEvents, 8);
424AssertCompileMemberSizeAlignment(DBGFCPU, aEvents[0], 8);
425/** Pointer to DBGFCPU data. */
426typedef DBGFCPU *PDBGFCPU;
427
428struct DBGFOSEMTWRAPPER;
429
430/**
431 * The DBGF data kept in the UVM.
432 */
433typedef struct DBGFUSERPERVM
434{
435 /** The address space database lock. */
436 RTSEMRW hAsDbLock;
437 /** The address space handle database. (Protected by hAsDbLock.) */
438 R3PTRTYPE(AVLPVTREE) AsHandleTree;
439 /** The address space process id database. (Protected by hAsDbLock.) */
440 R3PTRTYPE(AVLU32TREE) AsPidTree;
441 /** The address space name database. (Protected by hAsDbLock.) */
442 R3PTRTYPE(RTSTRSPACE) AsNameSpace;
443 /** Special address space aliases. (Protected by hAsDbLock.) */
444 RTDBGAS volatile ahAsAliases[DBGF_AS_COUNT];
445 /** For lazily populating the aliased address spaces. */
446 bool volatile afAsAliasPopuplated[DBGF_AS_COUNT];
447 /** Alignment padding. */
448 bool afAlignment1[2];
449 /** Debug configuration. */
450 R3PTRTYPE(RTDBGCFG) hDbgCfg;
451
452 /** The register database lock. */
453 RTSEMRW hRegDbLock;
454 /** String space for looking up registers. (Protected by hRegDbLock.) */
455 R3PTRTYPE(RTSTRSPACE) RegSpace;
456 /** String space holding the register sets. (Protected by hRegDbLock.) */
457 R3PTRTYPE(RTSTRSPACE) RegSetSpace;
458 /** The number of registers (aliases, sub-fields and the special CPU
459 * register aliases (eg AH) are not counted). */
460 uint32_t cRegs;
461 /** For early initialization by . */
462 bool volatile fRegDbInitialized;
463 /** Alignment padding. */
464 bool afAlignment2[3];
465
466 /** Critical section protecting the Guest OS Digger data, the info handlers
467 * and the plugins. These share to give the best possible plugin unload
468 * race protection. */
469 RTCRITSECTRW CritSect;
470 /** Head of the LIFO of loaded DBGF plugins. */
471 R3PTRTYPE(struct DBGFPLUGIN *) pPlugInHead;
472 /** The current Guest OS digger. */
473 R3PTRTYPE(PDBGFOS) pCurOS;
474 /** The head of the Guest OS digger instances. */
475 R3PTRTYPE(PDBGFOS) pOSHead;
476 /** List of registered info handlers. */
477 R3PTRTYPE(PDBGFINFO) pInfoFirst;
478
479 /** The type database lock. */
480 RTSEMRW hTypeDbLock;
481 /** String space for looking up types. (Protected by hTypeDbLock.) */
482 R3PTRTYPE(RTSTRSPACE) TypeSpace;
483 /** For early initialization by . */
484 bool volatile fTypeDbInitialized;
485 /** Alignment padding. */
486 bool afAlignment3[3];
487
488} DBGFUSERPERVM;
489typedef DBGFUSERPERVM *PDBGFUSERPERVM;
490typedef DBGFUSERPERVM const *PCDBGFUSERPERVM;
491
492/**
493 * The per-CPU DBGF data kept in the UVM.
494 */
495typedef struct DBGFUSERPERVMCPU
496{
497 /** The guest register set for this CPU. Can be NULL. */
498 R3PTRTYPE(struct DBGFREGSET *) pGuestRegSet;
499 /** The hypervisor register set for this CPU. Can be NULL. */
500 R3PTRTYPE(struct DBGFREGSET *) pHyperRegSet;
501} DBGFUSERPERVMCPU;
502
503
504#ifdef IN_RING3
505int dbgfR3AsInit(PUVM pUVM);
506void dbgfR3AsTerm(PUVM pUVM);
507void dbgfR3AsRelocate(PUVM pUVM, RTGCUINTPTR offDelta);
508int dbgfR3BpInit(PVM pVM);
509int dbgfR3InfoInit(PUVM pUVM);
510int dbgfR3InfoTerm(PUVM pUVM);
511int dbgfR3OSInit(PUVM pUVM);
512void dbgfR3OSTermPart1(PUVM pUVM);
513void dbgfR3OSTermPart2(PUVM pUVM);
514int dbgfR3OSStackUnwindAssist(PUVM pUVM, VMCPUID idCpu, PDBGFSTACKFRAME pFrame, PRTDBGUNWINDSTATE pState,
515 PCCPUMCTX pInitialCtx, RTDBGAS hAs, uint64_t *puScratch);
516int dbgfR3RegInit(PUVM pUVM);
517void dbgfR3RegTerm(PUVM pUVM);
518int dbgfR3TraceInit(PVM pVM);
519void dbgfR3TraceRelocate(PVM pVM);
520void dbgfR3TraceTerm(PVM pVM);
521DECLHIDDEN(int) dbgfR3TypeInit(PUVM pUVM);
522DECLHIDDEN(void) dbgfR3TypeTerm(PUVM pUVM);
523int dbgfR3PlugInInit(PUVM pUVM);
524void dbgfR3PlugInTerm(PUVM pUVM);
525int dbgfR3BugCheckInit(PVM pVM);
526
527/**
528 * DBGF disassembler state (substate of DISSTATE).
529 */
530typedef struct DBGFDISSTATE
531{
532 /** Pointer to the current instruction. */
533 PCDISOPCODE pCurInstr;
534 /** Size of the instruction in bytes. */
535 uint32_t cbInstr;
536 /** Parameters. */
537 DISOPPARAM Param1;
538 DISOPPARAM Param2;
539 DISOPPARAM Param3;
540 DISOPPARAM Param4;
541} DBGFDISSTATE;
542/** Pointer to a DBGF disassembler state. */
543typedef DBGFDISSTATE *PDBGFDISSTATE;
544
545DECLHIDDEN(int) dbgfR3DisasInstrStateEx(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddr, uint32_t fFlags,
546 char *pszOutput, uint32_t cbOutput, PDBGFDISSTATE pDisState);
547
548#endif /* IN_RING3 */
549
550/** @} */
551
552#endif /* !VMM_INCLUDED_SRC_include_DBGFInternal_h */
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