VirtualBox

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

Last change on this file since 86697 was 86683, checked in by vboxsync, 4 years ago

VMM/DBGF: Missing tracer destruction in R0 when the VM terminates, bugref:9210

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette