VirtualBox

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

Last change on this file since 84458 was 84458, checked in by vboxsync, 5 years ago

VMM/DBGF: First commit of new tracing facility, bugref:9210

The new DBGF tracing facility allows efficient capturing of events to a compact binary
trace log for later analysis. It is primarily intended for recording device/guest
interactions for now but can be extended easily for other types of events later on.
It supports capturing events happening in both R0 and R3 by using a shared ring buffer
to post events to. The events are processed by a dedicated I/O thread which writes
new events into the binary trace log file.

This is only the core VMM/DBGF part providing the API, the integration with PDM
comes in a separate commit.

Disabled by default for now because it is still work in progress,
enable with VBOX_WITH_DBGF_TRACING.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 33.8 KB
Line 
1/* $Id: DBGFInternal.h 84458 2020-05-22 12:51:49Z 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 <iprt/tracelog.h>
35#include <VBox/vmm/dbgf.h>
36
37
38
39/** @defgroup grp_dbgf_int Internals
40 * @ingroup grp_dbgf
41 * @internal
42 * @{
43 */
44
45/** The maximum tracer instance (total) size, ring-0/raw-mode capable tracers. */
46#define DBGF_MAX_TRACER_INSTANCE_SIZE _8M
47/** The maximum tracers instance (total) size, ring-3 only tracers. */
48#define DBGF_MAX_TRACER_INSTANCE_SIZE_R3 _16M
49/** Event ringbuffer header size. */
50#define DBGF_TRACER_EVT_HDR_SZ (32)
51/** Event ringbuffer payload size. */
52#define DBGF_TRACER_EVT_PAYLOAD_SZ (32)
53/** Event ringbuffer entry size. */
54#define DBGF_TRACER_EVT_SZ (DBGF_TRACER_EVT_HDR_SZ + DBGF_TRACER_EVT_PAYLOAD_SZ)
55
56
57
58/*******************************************************************************
59* Structures and Typedefs *
60*******************************************************************************/
61
62/**
63 * Event entry types.
64 */
65typedef enum DBGFTRACEREVT
66{
67 /** Invalid type. */
68 DBGFTRACEREVT_INVALID = 0,
69 /** MMIO map region event. */
70 DBGFTRACEREVT_MMIO_MAP,
71 /** MMIO unmap region event. */
72 DBGFTRACEREVT_MMIO_UNMAP,
73 /** MMIO read event. */
74 DBGFTRACEREVT_MMIO_READ,
75 /** MMIO write event. */
76 DBGFTRACEREVT_MMIO_WRITE,
77 /** MMIO fill event. */
78 DBGFTRACEREVT_MMIO_FILL,
79 /** I/O port map event. */
80 DBGFTRACEREVT_IOPORT_MAP,
81 /** I/O port unmap event. */
82 DBGFTRACEREVT_IOPORT_UNMAP,
83 /** I/O port read event. */
84 DBGFTRACEREVT_IOPORT_READ,
85 /** I/O port write event. */
86 DBGFTRACEREVT_IOPORT_WRITE,
87 /** IRQ event. */
88 DBGFTRACEREVT_IRQ,
89 /** I/O APIC MSI event. */
90 DBGFTRACEREVT_IOAPIC_MSI,
91 /** Read from guest physical memory. */
92 DBGFTRACEREVT_GCPHYS_READ,
93 /** Write to guest physical memory. */
94 DBGFTRACEREVT_GCPHYS_WRITE,
95 /** 32bit hack. */
96 DBGFTRACEREVT_32BIT_HACK
97} DBGFTRACEREVT;
98/** Pointer to a trace event entry type. */
99typedef DBGFTRACEREVT *PDBGFTRACEREVT;
100
101
102/**
103 * MMIO region map event.
104 */
105typedef struct DBGFTRACEREVTMMIOMAP
106{
107 /** Unique region handle for the event source. */
108 uint64_t hMmioRegion;
109 /** The base guest physical address of the MMIO region. */
110 RTGCPHYS GCPhysMmioBase;
111 /** Padding to 32byte. */
112 uint64_t au64Pad0[2];
113} DBGFTRACEREVTMMIOMAP;
114/** Pointer to a MMIO map event. */
115typedef DBGFTRACEREVTMMIOMAP *PDBGFTRACEREVTMMIOMAP;
116/** Pointer to a const MMIO map event. */
117typedef const DBGFTRACEREVTMMIOMAP *PCDBGFTRACEREVTMMIOMAP;
118
119AssertCompileSize(DBGFTRACEREVTMMIOMAP, DBGF_TRACER_EVT_PAYLOAD_SZ);
120
121
122/**
123 * MMIO region unmap event.
124 */
125typedef struct DBGFTRACEREVTMMIOUNMAP
126{
127 /** Unique region handle for the event source. */
128 uint64_t hMmioRegion;
129 /** Padding to 32byte. */
130 uint64_t au64Pad0[3];
131} DBGFTRACEREVTMMIOUNMAP;
132/** Pointer to a MMIO map event. */
133typedef DBGFTRACEREVTMMIOUNMAP *PDBGFTRACEREVTMMIOUNMAP;
134/** Pointer to a const MMIO map event. */
135typedef const DBGFTRACEREVTMMIOUNMAP *PCDBGFTRACEREVTMMIOUNMAP;
136
137AssertCompileSize(DBGFTRACEREVTMMIOUNMAP, DBGF_TRACER_EVT_PAYLOAD_SZ);
138
139
140/**
141 * MMIO event.
142 */
143typedef struct DBGFTRACEREVTMMIO
144{
145 /** Unique region handle for the event source. */
146 uint64_t hMmioRegion;
147 /** Offset into the region the access happened. */
148 RTGCPHYS offMmio;
149 /** Number of bytes transfered (the direction is in the event header). */
150 uint64_t cbXfer;
151 /** The value transfered. */
152 uint64_t u64Val;
153} DBGFTRACEREVTMMIO;
154/** Pointer to a MMIO event. */
155typedef DBGFTRACEREVTMMIO *PDBGFTRACEREVTMMIO;
156/** Pointer to a const MMIO event. */
157typedef const DBGFTRACEREVTMMIO *PCDBGFTRACEREVTMMIO;
158
159AssertCompileSize(DBGFTRACEREVTMMIO, DBGF_TRACER_EVT_PAYLOAD_SZ);
160
161
162/**
163 * MMIO fill event.
164 */
165typedef struct DBGFTRACEREVTMMIOFILL
166{
167 /** Unique region handle for the event source. */
168 uint64_t hMmioRegion;
169 /** Offset into the region the access happened. */
170 RTGCPHYS offMmio;
171 /** Item size in bytes. */
172 uint32_t cbItem;
173 /** Amount of items being filled. */
174 uint32_t cItems;
175 /** The fill value. */
176 uint32_t u32Item;
177 /** Padding to 32bytes. */
178 uint32_t u32Pad0;
179} DBGFTRACEREVTMMIOFILL;
180/** Pointer to a MMIO event. */
181typedef DBGFTRACEREVTMMIOFILL *PDBGFTRACEREVTMMIOFILL;
182/** Pointer to a const MMIO event. */
183typedef const DBGFTRACEREVTMMIOFILL *PCDBGFTRACEREVTMMIOFILL;
184
185AssertCompileSize(DBGFTRACEREVTMMIOFILL, DBGF_TRACER_EVT_PAYLOAD_SZ);
186
187
188/**
189 * I/O port region map event.
190 */
191typedef struct DBGFTRACEREVTIOPORTMAP
192{
193 /** Unique I/O port region handle for the event source. */
194 uint64_t hIoPorts;
195 /** The base I/O port for the region. */
196 RTIOPORT IoPortBase;
197 /** Padding to 32byte. */
198 uint16_t au16Pad0[11];
199} DBGFTRACEREVTIOPORTMAP;
200/** Pointer to a MMIO map event. */
201typedef DBGFTRACEREVTIOPORTMAP *PDBGFTRACEREVTIOPORTMAP;
202/** Pointer to a const MMIO map event. */
203typedef const DBGFTRACEREVTIOPORTMAP *PCDBGFTRACEREVTIOPORTMAP;
204
205AssertCompileSize(DBGFTRACEREVTIOPORTMAP, DBGF_TRACER_EVT_PAYLOAD_SZ);
206
207
208/**
209 * MMIO region unmap event.
210 */
211typedef struct DBGFTRACEREVTIOPORTUNMAP
212{
213 /** Unique region handle for the event source. */
214 uint64_t hIoPorts;
215 /** Padding to 32byte. */
216 uint64_t au64Pad0[3];
217} DBGFTRACEREVTIOPORTUNMAP;
218/** Pointer to a MMIO map event. */
219typedef DBGFTRACEREVTIOPORTUNMAP *PDBGFTRACEREVTIOPORTUNMAP;
220/** Pointer to a const MMIO map event. */
221typedef const DBGFTRACEREVTIOPORTUNMAP *PCDBGFTRACEREVTIOPORTUNMAP;
222
223AssertCompileSize(DBGFTRACEREVTIOPORTUNMAP, DBGF_TRACER_EVT_PAYLOAD_SZ);
224
225
226/**
227 * I/O port event.
228 */
229typedef struct DBGFTRACEREVTIOPORT
230{
231 /** Unique region handle for the event source. */
232 uint64_t hIoPorts;
233 /** Offset into the I/O port region. */
234 RTIOPORT offPort;
235 /** 8 byte alignment. */
236 uint8_t abPad0[6];
237 /** Number of bytes transfered (the direction is in the event header). */
238 uint64_t cbXfer;
239 /** The value transfered. */
240 uint32_t u32Val;
241 /** Padding to 32bytes. */
242 uint8_t abPad1[4];
243} DBGFTRACEREVTIOPORT;
244/** Pointer to a MMIO event. */
245typedef DBGFTRACEREVTIOPORT *PDBGFTRACEREVTIOPORT;
246/** Pointer to a const MMIO event. */
247typedef const DBGFTRACEREVTIOPORT *PCDBGFTRACEREVTIOPORT;
248
249AssertCompileSize(DBGFTRACEREVTIOPORT, DBGF_TRACER_EVT_PAYLOAD_SZ);
250
251
252/**
253 * IRQ event.
254 */
255typedef struct DBGFTRACEREVTIRQ
256{
257 /** The IRQ line. */
258 int32_t iIrq;
259 /** IRQ level flags. */
260 int32_t fIrqLvl;
261 /** Padding to 32bytes. */
262 uint32_t au32Pad0[6];
263} DBGFTRACEREVTIRQ;
264/** Pointer to a MMIO event. */
265typedef DBGFTRACEREVTIRQ *PDBGFTRACEREVTIRQ;
266/** Pointer to a const MMIO event. */
267typedef const DBGFTRACEREVTIRQ *PCDBGFTRACEREVTIRQ;
268
269AssertCompileSize(DBGFTRACEREVTIRQ, DBGF_TRACER_EVT_PAYLOAD_SZ);
270
271
272/**
273 * I/O APIC MSI event.
274 */
275typedef struct DBGFTRACEREVTIOAPICMSI
276{
277 /** The guest physical address being written. */
278 RTGCPHYS GCPhys;
279 /** The value being written. */
280 uint32_t u32Val;
281 /** Padding to 32bytes. */
282 uint32_t au32Pad0[5];
283} DBGFTRACEREVTIOAPICMSI;
284/** Pointer to a MMIO event. */
285typedef DBGFTRACEREVTIOAPICMSI *PDBGFTRACEREVTIOAPICMSI;
286/** Pointer to a const MMIO event. */
287typedef const DBGFTRACEREVTIOAPICMSI *PCDBGFTRACEREVTIOAPICMSI;
288
289AssertCompileSize(DBGFTRACEREVTIOAPICMSI, DBGF_TRACER_EVT_PAYLOAD_SZ);
290
291
292/**
293 * Guest physical memory transfer.
294 */
295typedef struct DBGFTRACEREVTGCPHYS
296{
297 /** Guest physical address of the access. */
298 RTGCPHYS GCPhys;
299 /** Number of bytes transfered (the direction is in the event header).
300 * If the number is small enough to fit into the remaining space of the entry
301 * it is stored here, otherwise it will be stored in the next entry (and following
302 * entries). */
303 uint64_t cbXfer;
304 /** Guest data being transfered. */
305 uint8_t abData[16];
306} DBGFTRACEREVTGCPHYS;
307/** Pointer to a guest physical memory transfer event. */
308typedef DBGFTRACEREVTGCPHYS *PDBGFTRACEREVTGCPHYS;
309/** Pointer to a const uest physical memory transfer event. */
310typedef const DBGFTRACEREVTGCPHYS *PCDBGFTRACEREVTGCPHYS;
311
312AssertCompileSize(DBGFTRACEREVTGCPHYS, DBGF_TRACER_EVT_PAYLOAD_SZ);
313
314
315/**
316 * A trace event header in the shared ring buffer.
317 */
318typedef struct DBGFTRACEREVTHDR
319{
320 /** Event ID. */
321 volatile uint64_t idEvt;
322 /** The previous event ID this one links to,
323 * DBGF_TRACER_EVT_HDR_ID_INVALID if it links to no other event. */
324 uint64_t idEvtPrev;
325 /** Event source. */
326 DBGFTRACEREVTSRC hEvtSrc;
327 /** The event entry type. */
328 DBGFTRACEREVT enmEvt;
329 /** Flags for this event. */
330 uint32_t fFlags;
331} DBGFTRACEREVTHDR;
332/** Pointer to a trace event header. */
333typedef DBGFTRACEREVTHDR *PDBGFTRACEREVTHDR;
334/** Pointer to a const trace event header. */
335typedef const DBGFTRACEREVTHDR *PCDBGFTRACEREVTHDR;
336
337AssertCompileSize(DBGFTRACEREVTHDR, DBGF_TRACER_EVT_HDR_SZ);
338
339/** Invalid event ID, this is always set by the flush thread after processing one entry
340 * so the producers know when they are about to overwrite not yet processed entries in the ring buffer. */
341#define DBGF_TRACER_EVT_HDR_ID_INVALID UINT64_C(0xffffffffffffffff)
342
343/** The event came from R0. */
344#define DBGF_TRACER_EVT_HDR_F_R0 RT_BIT(0)
345
346/** Default event header tracer flags. */
347#ifdef IN_RING0
348# define DBGF_TRACER_EVT_HDR_F_DEFAULT DBGF_TRACER_EVT_HDR_F_R0
349#else
350# define DBGF_TRACER_EVT_HDR_F_DEFAULT (0)
351#endif
352
353
354/**
355 * Tracer instance data, shared structure.
356 */
357typedef struct DBGFTRACERSHARED
358{
359 /** The global event ID counter, monotonically increasing.
360 * Accessed by all threads causing a trace event. */
361 volatile uint64_t idEvt;
362 /** The SUP event semaphore for poking the flush thread. */
363 SUPSEMEVENT hSupSemEvtFlush;
364 /** Ring buffer size. */
365 size_t cbRingBuf;
366 /** Flag whether there are events in the ring buffer to get processed. */
367 volatile bool fEvtsWaiting;
368 /** Flag whether the flush thread is actively running or was kicked. */
369 volatile bool fFlushThrdActive;
370 /** Padding to a 64byte alignment. */
371 uint8_t abAlignment0[32];
372} DBGFTRACERSHARED;
373/** Pointer to the shared tarcer instance data. */
374typedef DBGFTRACERSHARED *PDBGFTRACERSHARED;
375
376AssertCompileSizeAlignment(DBGFTRACERSHARED, 64);
377
378
379/**
380 * Tracer instance data, ring-3
381 */
382typedef struct DBGFTRACERINSR3
383{
384 /** Pointer to the next instance.
385 * (Head is pointed to by PDM::pTracerInstances.) */
386 R3PTRTYPE(struct DBGFTRACERINSR3 *) pNextR3;
387 /** R3 pointer to the VM this instance was created for. */
388 PVMR3 pVMR3;
389 /** Tracer instance number. */
390 uint32_t idTracer;
391 /** Flag whether the tracer has the R0 part enabled. */
392 bool fR0Enabled;
393 /** Flag whether the tracer flush thread should shut down. */
394 volatile bool fShutdown;
395 /** Padding. */
396 bool afPad0[6];
397 /** Next event source ID to return for a source registration. */
398 volatile DBGFTRACEREVTSRC hEvtSrcNext;
399 /** Pointer to the shared tracer instance data. */
400 R3PTRTYPE(PDBGFTRACERSHARED) pSharedR3;
401 /** The I/O thread writing the log from the shared event ringbuffer. */
402 RTTHREAD hThrdFlush;
403 /** Pointer to the start of the ring buffer. */
404 R3PTRTYPE(uint8_t *) pbRingBufR3;
405 /** The last processed event ID. */
406 uint64_t idEvtLast;
407 /** The trace log writer handle. */
408 RTTRACELOGWR hTraceLog;
409} DBGFTRACERINSR3;
410/** Pointer to a tarcer instance - Ring-3 Ptr. */
411typedef R3PTRTYPE(DBGFTRACERINSR3 *) PDBGFTRACERINSR3;
412
413
414/**
415 * Private tracer instance data, ring-0
416 */
417typedef struct DBGFTRACERINSR0
418{
419 /** Pointer to the VM this instance was created for. */
420 R0PTRTYPE(PGVM) pGVM;
421 /** The tracer instance memory. */
422 RTR0MEMOBJ hMemObj;
423 /** The ring-3 mapping object. */
424 RTR0MEMOBJ hMapObj;
425 /** Pointer to the shared tracer instance data. */
426 R0PTRTYPE(PDBGFTRACERSHARED) pSharedR0;
427 /** Size of the ring buffer in bytes, kept here so R3 can not manipulate the ring buffer
428 * size afterwards to trick R0 into doing something harmful. */
429 size_t cbRingBuf;
430 /** Pointer to the start of the ring buffer. */
431 R0PTRTYPE(uint8_t *) pbRingBufR0;
432} DBGFTRACERINSR0;
433/** Pointer to a VM - Ring-0 Ptr. */
434typedef R0PTRTYPE(DBGFTRACERINSR0 *) PDBGFTRACERINSR0;
435
436
437/**
438 * Private device instance data, raw-mode
439 */
440typedef struct DBGFTRACERINSRC
441{
442 /** Pointer to the VM this instance was created for. */
443 RGPTRTYPE(PVM) pVMRC;
444} DBGFTRACERINSRC;
445
446
447/** VMM Debugger Command. */
448typedef enum DBGFCMD
449{
450 /** No command.
451 * This is assigned to the field by the emulation thread after
452 * a command has been completed. */
453 DBGFCMD_NO_COMMAND = 0,
454 /** Halt the VM. */
455 DBGFCMD_HALT,
456 /** Resume execution. */
457 DBGFCMD_GO,
458 /** Single step execution - stepping into calls. */
459 DBGFCMD_SINGLE_STEP,
460 /** Detaches the debugger.
461 * Disabling all breakpoints, watch points and the like. */
462 DBGFCMD_DETACH_DEBUGGER,
463 /** Detached the debugger.
464 * The isn't a command as such, it's just that it's necessary for the
465 * detaching protocol to be racefree. */
466 DBGFCMD_DETACHED_DEBUGGER
467} DBGFCMD;
468
469/**
470 * VMM Debugger Command.
471 */
472typedef union DBGFCMDDATA
473{
474 uint32_t uDummy;
475} DBGFCMDDATA;
476/** Pointer to DBGF Command Data. */
477typedef DBGFCMDDATA *PDBGFCMDDATA;
478
479/**
480 * Info type.
481 */
482typedef enum DBGFINFOTYPE
483{
484 /** Invalid. */
485 DBGFINFOTYPE_INVALID = 0,
486 /** Device owner. */
487 DBGFINFOTYPE_DEV,
488 /** Driver owner. */
489 DBGFINFOTYPE_DRV,
490 /** Internal owner. */
491 DBGFINFOTYPE_INT,
492 /** External owner. */
493 DBGFINFOTYPE_EXT,
494 /** Device owner. */
495 DBGFINFOTYPE_DEV_ARGV,
496 /** Driver owner. */
497 DBGFINFOTYPE_DRV_ARGV,
498 /** USB device owner. */
499 DBGFINFOTYPE_USB_ARGV,
500 /** Internal owner, argv. */
501 DBGFINFOTYPE_INT_ARGV,
502 /** External owner. */
503 DBGFINFOTYPE_EXT_ARGV
504} DBGFINFOTYPE;
505
506
507/** Pointer to info structure. */
508typedef struct DBGFINFO *PDBGFINFO;
509
510#ifdef IN_RING3
511/**
512 * Info structure.
513 */
514typedef struct DBGFINFO
515{
516 /** The flags. */
517 uint32_t fFlags;
518 /** Owner type. */
519 DBGFINFOTYPE enmType;
520 /** Per type data. */
521 union
522 {
523 /** DBGFINFOTYPE_DEV */
524 struct
525 {
526 /** Device info handler function. */
527 PFNDBGFHANDLERDEV pfnHandler;
528 /** The device instance. */
529 PPDMDEVINS pDevIns;
530 } Dev;
531
532 /** DBGFINFOTYPE_DRV */
533 struct
534 {
535 /** Driver info handler function. */
536 PFNDBGFHANDLERDRV pfnHandler;
537 /** The driver instance. */
538 PPDMDRVINS pDrvIns;
539 } Drv;
540
541 /** DBGFINFOTYPE_INT */
542 struct
543 {
544 /** Internal info handler function. */
545 PFNDBGFHANDLERINT pfnHandler;
546 } Int;
547
548 /** DBGFINFOTYPE_EXT */
549 struct
550 {
551 /** External info handler function. */
552 PFNDBGFHANDLEREXT pfnHandler;
553 /** The user argument. */
554 void *pvUser;
555 } Ext;
556
557 /** DBGFINFOTYPE_DEV_ARGV */
558 struct
559 {
560 /** Device info handler function. */
561 PFNDBGFINFOARGVDEV pfnHandler;
562 /** The device instance. */
563 PPDMDEVINS pDevIns;
564 } DevArgv;
565
566 /** DBGFINFOTYPE_DRV_ARGV */
567 struct
568 {
569 /** Driver info handler function. */
570 PFNDBGFINFOARGVDRV pfnHandler;
571 /** The driver instance. */
572 PPDMDRVINS pDrvIns;
573 } DrvArgv;
574
575 /** DBGFINFOTYPE_USB_ARGV */
576 struct
577 {
578 /** Driver info handler function. */
579 PFNDBGFINFOARGVUSB pfnHandler;
580 /** The driver instance. */
581 PPDMUSBINS pUsbIns;
582 } UsbArgv;
583
584 /** DBGFINFOTYPE_INT_ARGV */
585 struct
586 {
587 /** Internal info handler function. */
588 PFNDBGFINFOARGVINT pfnHandler;
589 } IntArgv;
590
591 /** DBGFINFOTYPE_EXT_ARGV */
592 struct
593 {
594 /** External info handler function. */
595 PFNDBGFINFOARGVEXT pfnHandler;
596 /** The user argument. */
597 void *pvUser;
598 } ExtArgv;
599 } u;
600
601 /** Pointer to the description. */
602 const char *pszDesc;
603 /** Pointer to the next info structure. */
604 PDBGFINFO pNext;
605 /** The identifier name length. */
606 size_t cchName;
607 /** The identifier name. (Extends 'beyond' the struct as usual.) */
608 char szName[1];
609} DBGFINFO;
610#endif /* IN_RING3 */
611
612
613#ifdef IN_RING3
614/**
615 * Guest OS digger instance.
616 */
617typedef struct DBGFOS
618{
619 /** Pointer to the registration record. */
620 PCDBGFOSREG pReg;
621 /** Pointer to the next OS we've registered. */
622 struct DBGFOS *pNext;
623 /** List of EMT interface wrappers. */
624 struct DBGFOSEMTWRAPPER *pWrapperHead;
625 /** The instance data (variable size). */
626 uint8_t abData[16];
627} DBGFOS;
628#endif
629/** Pointer to guest OS digger instance. */
630typedef struct DBGFOS *PDBGFOS;
631/** Pointer to const guest OS digger instance. */
632typedef struct DBGFOS const *PCDBGFOS;
633
634
635/**
636 * Breakpoint search optimization.
637 */
638typedef struct DBGFBPSEARCHOPT
639{
640 /** Where to start searching for hits.
641 * (First enabled is #DBGF::aBreakpoints[iStartSearch]). */
642 uint32_t volatile iStartSearch;
643 /** The number of aBreakpoints entries to search.
644 * (Last enabled is #DBGF::aBreakpoints[iStartSearch + cToSearch - 1]) */
645 uint32_t volatile cToSearch;
646} DBGFBPSEARCHOPT;
647/** Pointer to a breakpoint search optimziation structure. */
648typedef DBGFBPSEARCHOPT *PDBGFBPSEARCHOPT;
649
650
651
652/**
653 * DBGF Data (part of VM)
654 */
655typedef struct DBGF
656{
657 /** Bitmap of enabled hardware interrupt breakpoints. */
658 uint32_t bmHardIntBreakpoints[256 / 32];
659 /** Bitmap of enabled software interrupt breakpoints. */
660 uint32_t bmSoftIntBreakpoints[256 / 32];
661 /** Bitmap of selected events.
662 * This includes non-selectable events too for simplicity, we maintain the
663 * state for some of these, as it may come in handy. */
664 uint64_t bmSelectedEvents[(DBGFEVENT_END + 63) / 64];
665
666 /** Enabled hardware interrupt breakpoints. */
667 uint32_t cHardIntBreakpoints;
668 /** Enabled software interrupt breakpoints. */
669 uint32_t cSoftIntBreakpoints;
670
671 /** The number of selected events. */
672 uint32_t cSelectedEvents;
673
674 /** The number of enabled hardware breakpoints. */
675 uint8_t cEnabledHwBreakpoints;
676 /** The number of enabled hardware I/O breakpoints. */
677 uint8_t cEnabledHwIoBreakpoints;
678 /** The number of enabled INT3 breakpoints. */
679 uint8_t cEnabledInt3Breakpoints;
680 uint8_t abPadding; /**< Unused padding space up for grabs. */
681 uint32_t uPadding;
682
683 /** Debugger Attached flag.
684 * Set if a debugger is attached, elsewise it's clear.
685 */
686 bool volatile fAttached;
687
688 /** Stopped in the Hypervisor.
689 * Set if we're stopped on a trace, breakpoint or assertion inside
690 * the hypervisor and have to restrict the available operations.
691 */
692 bool volatile fStoppedInHyper;
693
694 /**
695 * Ping-Pong construct where the Ping side is the VMM and the Pong side
696 * the Debugger.
697 */
698 RTPINGPONG PingPong;
699 RTHCUINTPTR uPtrPadding; /**< Alignment padding. */
700
701 /** The Event to the debugger.
702 * The VMM will ping the debugger when the event is ready. The event is
703 * either a response to a command or to a break/watch point issued
704 * previously.
705 */
706 DBGFEVENT DbgEvent;
707
708 /** The Command to the VMM.
709 * Operated in an atomic fashion since the VMM will poll on this.
710 * This means that a the command data must be written before this member
711 * is set. The VMM will reset this member to the no-command state
712 * when it have processed it.
713 */
714 DBGFCMD volatile enmVMMCmd;
715 /** The Command data.
716 * Not all commands take data. */
717 DBGFCMDDATA VMMCmdData;
718
719 /** Stepping filtering. */
720 struct
721 {
722 /** The CPU doing the stepping.
723 * Set to NIL_VMCPUID when filtering is inactive */
724 VMCPUID idCpu;
725 /** The specified flags. */
726 uint32_t fFlags;
727 /** The effective PC address to stop at, if given. */
728 RTGCPTR AddrPc;
729 /** The lowest effective stack address to stop at.
730 * Together with cbStackPop, this forms a range of effective stack pointer
731 * addresses that we stop for. */
732 RTGCPTR AddrStackPop;
733 /** The size of the stack stop area starting at AddrStackPop. */
734 RTGCPTR cbStackPop;
735 /** Maximum number of steps. */
736 uint32_t cMaxSteps;
737
738 /** Number of steps made thus far. */
739 uint32_t cSteps;
740 /** Current call counting balance for step-over handling. */
741 uint32_t uCallDepth;
742
743 uint32_t u32Padding; /**< Alignment padding. */
744
745 } SteppingFilter;
746
747 uint32_t u32Padding[2]; /**< Alignment padding. */
748
749 /** Array of hardware breakpoints. (0..3)
750 * This is shared among all the CPUs because life is much simpler that way. */
751 DBGFBP aHwBreakpoints[4];
752 /** Array of int 3 and REM breakpoints. (4..)
753 * @remark This is currently a fixed size array for reasons of simplicity. */
754 DBGFBP aBreakpoints[32];
755
756 /** MMIO breakpoint search optimizations. */
757 DBGFBPSEARCHOPT Mmio;
758 /** I/O port breakpoint search optimizations. */
759 DBGFBPSEARCHOPT PortIo;
760 /** INT3 breakpoint search optimizations. */
761 DBGFBPSEARCHOPT Int3;
762
763 /**
764 * Bug check data.
765 * @note This will not be reset on reset.
766 */
767 struct
768 {
769 /** The ID of the CPU reporting it. */
770 VMCPUID idCpu;
771 /** The event associated with the bug check (gives source).
772 * This is set to DBGFEVENT_END if no BSOD data here. */
773 DBGFEVENTTYPE enmEvent;
774 /** The total reset count at the time (VMGetResetCount). */
775 uint32_t uResetNo;
776 /** Explicit padding. */
777 uint32_t uPadding;
778 /** When it was reported (TMVirtualGet). */
779 uint64_t uTimestamp;
780 /** The bug check number.
781 * @note This is really just 32-bit wide, see KeBugCheckEx. */
782 uint64_t uBugCheck;
783 /** The bug check parameters. */
784 uint64_t auParameters[4];
785 } BugCheck;
786} DBGF;
787AssertCompileMemberAlignment(DBGF, DbgEvent, 8);
788AssertCompileMemberAlignment(DBGF, aHwBreakpoints, 8);
789AssertCompileMemberAlignment(DBGF, bmHardIntBreakpoints, 8);
790/** Pointer to DBGF Data. */
791typedef DBGF *PDBGF;
792
793
794/**
795 * Event state (for DBGFCPU::aEvents).
796 */
797typedef enum DBGFEVENTSTATE
798{
799 /** Invalid event stack entry. */
800 DBGFEVENTSTATE_INVALID = 0,
801 /** The current event stack entry. */
802 DBGFEVENTSTATE_CURRENT,
803 /** Event that should be ignored but hasn't yet actually been ignored. */
804 DBGFEVENTSTATE_IGNORE,
805 /** Event that has been ignored but may be restored to IGNORE should another
806 * debug event fire before the instruction is completed. */
807 DBGFEVENTSTATE_RESTORABLE,
808 /** End of valid events. */
809 DBGFEVENTSTATE_END,
810 /** Make sure we've got a 32-bit type. */
811 DBGFEVENTSTATE_32BIT_HACK = 0x7fffffff
812} DBGFEVENTSTATE;
813
814
815/** Converts a DBGFCPU pointer into a VM pointer. */
816#define DBGFCPU_2_VM(pDbgfCpu) ((PVM)((uint8_t *)(pDbgfCpu) + (pDbgfCpu)->offVM))
817
818/**
819 * The per CPU data for DBGF.
820 */
821typedef struct DBGFCPU
822{
823 /** The offset into the VM structure.
824 * @see DBGFCPU_2_VM(). */
825 uint32_t offVM;
826
827 /** Current active breakpoint (id).
828 * This is ~0U if not active. It is set when a execution engine
829 * encounters a breakpoint and returns VINF_EM_DBG_BREAKPOINT. This is
830 * currently not used for REM breakpoints because of the lazy coupling
831 * between VBox and REM.
832 *
833 * @todo drop this in favor of aEvents! */
834 uint32_t iActiveBp;
835 /** Set if we're singlestepping in raw mode.
836 * This is checked and cleared in the \#DB handler. */
837 bool fSingleSteppingRaw;
838
839 /** Alignment padding. */
840 bool afPadding[3];
841
842 /** The number of events on the stack (aEvents).
843 * The pending event is the last one (aEvents[cEvents - 1]), but only when
844 * enmState is DBGFEVENTSTATE_CURRENT. */
845 uint32_t cEvents;
846 /** Events - current, ignoring and ignored.
847 *
848 * We maintain a stack of events in order to try avoid ending up in an infinit
849 * loop when resuming after an event fired. There are cases where we may end
850 * generating additional events before the instruction can be executed
851 * successfully. Like for instance an XCHG on MMIO with separate read and write
852 * breakpoints, or a MOVSB instruction working on breakpointed MMIO as both
853 * source and destination.
854 *
855 * So, when resuming after dropping into the debugger for an event, we convert
856 * the DBGFEVENTSTATE_CURRENT event into a DBGFEVENTSTATE_IGNORE event, leaving
857 * cEvents unchanged. If the event is reported again, we will ignore it and
858 * tell the reporter to continue executing. The event change to the
859 * DBGFEVENTSTATE_RESTORABLE state.
860 *
861 * Currently, the event reporter has to figure out that it is a nested event and
862 * tell DBGF to restore DBGFEVENTSTATE_RESTORABLE events (and keep
863 * DBGFEVENTSTATE_IGNORE, should they happen out of order for some weird
864 * reason).
865 */
866 struct
867 {
868 /** The event details. */
869 DBGFEVENT Event;
870 /** The RIP at which this happend (for validating ignoring). */
871 uint64_t rip;
872 /** The event state. */
873 DBGFEVENTSTATE enmState;
874 /** Alignment padding. */
875 uint32_t u32Alignment;
876 } aEvents[3];
877} DBGFCPU;
878AssertCompileMemberAlignment(DBGFCPU, aEvents, 8);
879AssertCompileMemberSizeAlignment(DBGFCPU, aEvents[0], 8);
880/** Pointer to DBGFCPU data. */
881typedef DBGFCPU *PDBGFCPU;
882
883struct DBGFOSEMTWRAPPER;
884
885/**
886 * DBGF data kept in the ring-0 GVM.
887 */
888typedef struct DBGFR0PERVM
889{
890 /** Pointer to the tracer instance if enabled. */
891 R0PTRTYPE(struct DBGFTRACERINSR0 *) pTracerR0;
892} DBGFR0PERVM;
893
894/**
895 * The DBGF data kept in the UVM.
896 */
897typedef struct DBGFUSERPERVM
898{
899 /** The address space database lock. */
900 RTSEMRW hAsDbLock;
901 /** The address space handle database. (Protected by hAsDbLock.) */
902 R3PTRTYPE(AVLPVTREE) AsHandleTree;
903 /** The address space process id database. (Protected by hAsDbLock.) */
904 R3PTRTYPE(AVLU32TREE) AsPidTree;
905 /** The address space name database. (Protected by hAsDbLock.) */
906 R3PTRTYPE(RTSTRSPACE) AsNameSpace;
907 /** Special address space aliases. (Protected by hAsDbLock.) */
908 RTDBGAS volatile ahAsAliases[DBGF_AS_COUNT];
909 /** For lazily populating the aliased address spaces. */
910 bool volatile afAsAliasPopuplated[DBGF_AS_COUNT];
911 /** Alignment padding. */
912 bool afAlignment1[2];
913 /** Debug configuration. */
914 R3PTRTYPE(RTDBGCFG) hDbgCfg;
915
916 /** The register database lock. */
917 RTSEMRW hRegDbLock;
918 /** String space for looking up registers. (Protected by hRegDbLock.) */
919 R3PTRTYPE(RTSTRSPACE) RegSpace;
920 /** String space holding the register sets. (Protected by hRegDbLock.) */
921 R3PTRTYPE(RTSTRSPACE) RegSetSpace;
922 /** The number of registers (aliases, sub-fields and the special CPU
923 * register aliases (eg AH) are not counted). */
924 uint32_t cRegs;
925 /** For early initialization by . */
926 bool volatile fRegDbInitialized;
927 /** Alignment padding. */
928 bool afAlignment2[3];
929
930 /** Critical section protecting the Guest OS Digger data, the info handlers
931 * and the plugins. These share to give the best possible plugin unload
932 * race protection. */
933 RTCRITSECTRW CritSect;
934 /** Head of the LIFO of loaded DBGF plugins. */
935 R3PTRTYPE(struct DBGFPLUGIN *) pPlugInHead;
936 /** The current Guest OS digger. */
937 R3PTRTYPE(PDBGFOS) pCurOS;
938 /** The head of the Guest OS digger instances. */
939 R3PTRTYPE(PDBGFOS) pOSHead;
940 /** List of registered info handlers. */
941 R3PTRTYPE(PDBGFINFO) pInfoFirst;
942
943 /** The configured tracer. */
944 PDBGFTRACERINSR3 pTracerR3;
945
946 /** The type database lock. */
947 RTSEMRW hTypeDbLock;
948 /** String space for looking up types. (Protected by hTypeDbLock.) */
949 R3PTRTYPE(RTSTRSPACE) TypeSpace;
950 /** For early initialization by . */
951 bool volatile fTypeDbInitialized;
952 /** Alignment padding. */
953 bool afAlignment3[3];
954
955} DBGFUSERPERVM;
956typedef DBGFUSERPERVM *PDBGFUSERPERVM;
957typedef DBGFUSERPERVM const *PCDBGFUSERPERVM;
958
959/**
960 * The per-CPU DBGF data kept in the UVM.
961 */
962typedef struct DBGFUSERPERVMCPU
963{
964 /** The guest register set for this CPU. Can be NULL. */
965 R3PTRTYPE(struct DBGFREGSET *) pGuestRegSet;
966 /** The hypervisor register set for this CPU. Can be NULL. */
967 R3PTRTYPE(struct DBGFREGSET *) pHyperRegSet;
968} DBGFUSERPERVMCPU;
969
970
971#ifdef IN_RING3
972int dbgfR3AsInit(PUVM pUVM);
973void dbgfR3AsTerm(PUVM pUVM);
974void dbgfR3AsRelocate(PUVM pUVM, RTGCUINTPTR offDelta);
975int dbgfR3BpInit(PVM pVM);
976int dbgfR3InfoInit(PUVM pUVM);
977int dbgfR3InfoTerm(PUVM pUVM);
978int dbgfR3OSInit(PUVM pUVM);
979void dbgfR3OSTermPart1(PUVM pUVM);
980void dbgfR3OSTermPart2(PUVM pUVM);
981int dbgfR3OSStackUnwindAssist(PUVM pUVM, VMCPUID idCpu, PDBGFSTACKFRAME pFrame, PRTDBGUNWINDSTATE pState,
982 PCCPUMCTX pInitialCtx, RTDBGAS hAs, uint64_t *puScratch);
983int dbgfR3RegInit(PUVM pUVM);
984void dbgfR3RegTerm(PUVM pUVM);
985int dbgfR3TraceInit(PVM pVM);
986void dbgfR3TraceRelocate(PVM pVM);
987void dbgfR3TraceTerm(PVM pVM);
988DECLHIDDEN(int) dbgfR3TypeInit(PUVM pUVM);
989DECLHIDDEN(void) dbgfR3TypeTerm(PUVM pUVM);
990int dbgfR3PlugInInit(PUVM pUVM);
991void dbgfR3PlugInTerm(PUVM pUVM);
992int dbgfR3BugCheckInit(PVM pVM);
993DECLHIDDEN(int) dbgfR3TracerInit(PVM pVM);
994DECLHIDDEN(void) dbgfR3TracerTerm(PVM pVM);
995
996/**
997 * DBGF disassembler state (substate of DISSTATE).
998 */
999typedef struct DBGFDISSTATE
1000{
1001 /** Pointer to the current instruction. */
1002 PCDISOPCODE pCurInstr;
1003 /** Size of the instruction in bytes. */
1004 uint32_t cbInstr;
1005 /** Parameters. */
1006 DISOPPARAM Param1;
1007 DISOPPARAM Param2;
1008 DISOPPARAM Param3;
1009 DISOPPARAM Param4;
1010} DBGFDISSTATE;
1011/** Pointer to a DBGF disassembler state. */
1012typedef DBGFDISSTATE *PDBGFDISSTATE;
1013
1014DECLHIDDEN(int) dbgfR3DisasInstrStateEx(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddr, uint32_t fFlags,
1015 char *pszOutput, uint32_t cbOutput, PDBGFDISSTATE pDisState);
1016
1017#endif /* IN_RING3 */
1018
1019/** @} */
1020
1021#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