VirtualBox

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

Last change on this file since 74878 was 73460, checked in by vboxsync, 6 years ago

IPRT,DBGF,Diggers: Moved DBGFRETURNTYPE and the unwind state structure to IPRT (dbg.h) in prep for debug module interface and more. Added stack unwind assist callback for the OS diggers so they can identify special stack frames and supply more info via the sure-register-value array and frame flags. Identify and decode NT/AMD64 trap frames.

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