VirtualBox

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

Last change on this file since 84044 was 82968, checked in by vboxsync, 4 years ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use