VirtualBox

source: vbox/trunk/include/VBox/dbg.h@ 92989

Last change on this file since 92989 was 90837, checked in by vboxsync, 3 years ago

VMM: Doxygen fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 39.5 KB
Line 
1/** @file
2 * Debugger Interfaces. (VBoxDbg)
3 *
4 * This header covers all external interfaces of the Debugger module.
5 * However, it does not cover the DBGF interface since that part of the
6 * VMM. Use dbgf.h for that.
7 */
8
9/*
10 * Copyright (C) 2006-2020 Oracle Corporation
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.virtualbox.org. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License (GPL) as published by the Free Software
16 * Foundation, in version 2 as it comes in the "COPYING" file of the
17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 *
20 * The contents of this file may alternatively be used under the terms
21 * of the Common Development and Distribution License Version 1.0
22 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
23 * VirtualBox OSE distribution, in which case the provisions of the
24 * CDDL are applicable instead of those of the GPL.
25 *
26 * You may elect to license modified versions of this file under the
27 * terms and conditions of either the GPL or the CDDL or both.
28 */
29
30#ifndef VBOX_INCLUDED_dbg_h
31#define VBOX_INCLUDED_dbg_h
32#ifndef RT_WITHOUT_PRAGMA_ONCE
33# pragma once
34#endif
35
36#include <VBox/cdefs.h>
37#include <VBox/types.h>
38#include <VBox/vmm/dbgf.h>
39
40#include <iprt/stdarg.h>
41#ifdef IN_RING3
42# include <iprt/errcore.h>
43#endif
44
45RT_C_DECLS_BEGIN
46
47
48
49/** @defgroup grp_dbg The VirtualBox Debugger
50 * @{
51 */
52
53#ifdef IN_RING3 /* The debugger stuff is ring-3 only. */
54
55/** @defgroup grp_dbgc The Debugger Console API
56 * @{
57 */
58
59/** @def VBOX_WITH_DEBUGGER
60 * The build is with debugger module. Test if this is defined before registering
61 * external debugger commands. This is normally defined in Config.kmk.
62 */
63#ifdef DOXYGEN_RUNNING
64# define VBOX_WITH_DEBUGGER
65#endif
66
67
68/**
69 * DBGC variable category.
70 *
71 * Used to describe an argument to a command or function and a functions
72 * return value.
73 */
74typedef enum DBGCVARCAT
75{
76 /** Any type is fine. */
77 DBGCVAR_CAT_ANY = 0,
78 /** Any kind of pointer or number. */
79 DBGCVAR_CAT_POINTER_NUMBER,
80 /** Any kind of pointer or number, no range. */
81 DBGCVAR_CAT_POINTER_NUMBER_NO_RANGE,
82 /** Any kind of pointer. */
83 DBGCVAR_CAT_POINTER,
84 /** Any kind of pointer with no range option. */
85 DBGCVAR_CAT_POINTER_NO_RANGE,
86 /** GC pointer. */
87 DBGCVAR_CAT_GC_POINTER,
88 /** GC pointer with no range option. */
89 DBGCVAR_CAT_GC_POINTER_NO_RANGE,
90 /** Numeric argument. */
91 DBGCVAR_CAT_NUMBER,
92 /** Numeric argument with no range option. */
93 DBGCVAR_CAT_NUMBER_NO_RANGE,
94 /** String. */
95 DBGCVAR_CAT_STRING,
96 /** Symbol. */
97 DBGCVAR_CAT_SYMBOL,
98 /** Option. */
99 DBGCVAR_CAT_OPTION,
100 /** Option + string. */
101 DBGCVAR_CAT_OPTION_STRING,
102 /** Option + number. */
103 DBGCVAR_CAT_OPTION_NUMBER
104} DBGCVARCAT;
105
106
107/**
108 * DBGC variable type.
109 */
110typedef enum DBGCVARTYPE
111{
112 /** unknown... */
113 DBGCVAR_TYPE_UNKNOWN = 0,
114 /** Flat GC pointer. */
115 DBGCVAR_TYPE_GC_FLAT,
116 /** Segmented GC pointer. */
117 DBGCVAR_TYPE_GC_FAR,
118 /** Physical GC pointer. */
119 DBGCVAR_TYPE_GC_PHYS,
120 /** Flat HC pointer. */
121 DBGCVAR_TYPE_HC_FLAT,
122 /** Physical HC pointer. */
123 DBGCVAR_TYPE_HC_PHYS,
124 /** Number. */
125 DBGCVAR_TYPE_NUMBER,
126 /** String. */
127 DBGCVAR_TYPE_STRING,
128 /** Symbol. */
129 DBGCVAR_TYPE_SYMBOL,
130 /** Special type used when querying symbols. */
131 DBGCVAR_TYPE_ANY
132} DBGCVARTYPE;
133
134/** @todo Rename to DBGCVAR_IS_xyz. */
135
136/** Checks if the specified variable type is of a pointer persuasion. */
137#define DBGCVAR_ISPOINTER(enmType) ((enmType) >= DBGCVAR_TYPE_GC_FLAT && enmType <= DBGCVAR_TYPE_HC_PHYS)
138/** Checks if the specified variable type is of a pointer persuasion. */
139#define DBGCVAR_IS_FAR_PTR(enmType) ((enmType) == DBGCVAR_TYPE_GC_FAR)
140/** Checks if the specified variable type is of a pointer persuasion and of the guest context sort. */
141#define DBGCVAR_ISGCPOINTER(enmType) ((enmType) >= DBGCVAR_TYPE_GC_FLAT && (enmType) <= DBGCVAR_TYPE_GC_PHYS)
142/** Checks if the specified variable type is of a pointer persuasion and of the host context sort. */
143#define DBGCVAR_ISHCPOINTER(enmType) ((enmType) >= DBGCVAR_TYPE_HC_FLAT && (enmType) <= DBGCVAR_TYPE_HC_PHYS)
144
145
146/**
147 * DBGC variable range type.
148 */
149typedef enum DBGCVARRANGETYPE
150{
151 /** No range appliable or no range specified. */
152 DBGCVAR_RANGE_NONE = 0,
153 /** Number of elements. */
154 DBGCVAR_RANGE_ELEMENTS,
155 /** Number of bytes. */
156 DBGCVAR_RANGE_BYTES
157} DBGCVARRANGETYPE;
158
159
160/**
161 * Variable descriptor.
162 */
163typedef struct DBGCVARDESC
164{
165 /** The minimal number of times this argument may occur.
166 * Use 0 here to inidicate that the argument is optional. */
167 unsigned cTimesMin;
168 /** Maximum number of occurrences.
169 * Use ~0 here to indicate infinite. */
170 unsigned cTimesMax;
171 /** Argument category. */
172 DBGCVARCAT enmCategory;
173 /** Flags, DBGCVD_FLAGS_* */
174 unsigned fFlags;
175 /** Argument name. */
176 const char *pszName;
177 /** Argument name. */
178 const char *pszDescription;
179} DBGCVARDESC;
180/** Pointer to an argument descriptor. */
181typedef DBGCVARDESC *PDBGCVARDESC;
182/** Pointer to a const argument descriptor. */
183typedef const DBGCVARDESC *PCDBGCVARDESC;
184
185/** Variable descriptor flags.
186 * @{ */
187/** Indicates that the variable depends on the previous being present. */
188#define DBGCVD_FLAGS_DEP_PREV RT_BIT(1)
189/** @} */
190
191
192/**
193 * DBGC variable.
194 */
195typedef struct DBGCVAR
196{
197 /** Pointer to the argument descriptor. */
198 PCDBGCVARDESC pDesc;
199 /** Pointer to the next argument. */
200 struct DBGCVAR *pNext;
201
202 /** Argument type. */
203 DBGCVARTYPE enmType;
204 /** Type specific. */
205 union
206 {
207 /** Flat GC Address. (DBGCVAR_TYPE_GC_FLAT) */
208 RTGCPTR GCFlat;
209 /** Far (16:32) GC Address. (DBGCVAR_TYPE_GC_FAR) */
210 RTFAR32 GCFar;
211 /** Physical GC Address. (DBGCVAR_TYPE_GC_PHYS) */
212 RTGCPHYS GCPhys;
213 /** Flat HC Address. (DBGCVAR_TYPE_HC_FLAT) */
214 void *pvHCFlat;
215 /** Physical GC Address. (DBGCVAR_TYPE_HC_PHYS) */
216 RTHCPHYS HCPhys;
217 /** String. (DBGCVAR_TYPE_STRING)
218 * The basic idea is the the this is a pointer to the expression we're
219 * parsing, so no messing with freeing. */
220 const char *pszString;
221 /** Number. (DBGCVAR_TYPE_NUMBER) */
222 uint64_t u64Number;
223 } u;
224
225 /** Range type. */
226 DBGCVARRANGETYPE enmRangeType;
227 /** Range. The use of the content depends on the enmRangeType. */
228 uint64_t u64Range;
229} DBGCVAR;
230/** Pointer to a command argument. */
231typedef DBGCVAR *PDBGCVAR;
232/** Pointer to a const command argument. */
233typedef const DBGCVAR *PCDBGCVAR;
234
235
236/**
237 * Macro for initializing a DBGC variable with defaults.
238 * The result is an unknown variable type without any range.
239 */
240#define DBGCVAR_INIT(pVar) \
241 do { \
242 (pVar)->pDesc = NULL;\
243 (pVar)->pNext = NULL; \
244 (pVar)->enmType = DBGCVAR_TYPE_UNKNOWN; \
245 (pVar)->u.u64Number = 0; \
246 (pVar)->enmRangeType = DBGCVAR_RANGE_NONE; \
247 (pVar)->u64Range = 0; \
248 } while (0)
249
250/**
251 * Macro for initializing a DBGC variable with a HC physical address.
252 */
253#define DBGCVAR_INIT_HC_PHYS(pVar, Phys) \
254 do { \
255 DBGCVAR_INIT(pVar); \
256 (pVar)->enmType = DBGCVAR_TYPE_HC_PHYS; \
257 (pVar)->u.HCPhys = (Phys); \
258 } while (0)
259
260/**
261 * Macro for initializing a DBGC variable with a HC flat address.
262 */
263#define DBGCVAR_INIT_HC_FLAT(pVar, Flat) \
264 do { \
265 DBGCVAR_INIT(pVar); \
266 (pVar)->enmType = DBGCVAR_TYPE_HC_FLAT; \
267 (pVar)->u.pvHCFlat = (Flat); \
268 } while (0)
269
270/**
271 * Macro for initializing a DBGC variable with a GC physical address.
272 */
273#define DBGCVAR_INIT_GC_PHYS(pVar, Phys) \
274 do { \
275 DBGCVAR_INIT(pVar); \
276 (pVar)->enmType = DBGCVAR_TYPE_GC_PHYS; \
277 (pVar)->u.GCPhys = (Phys); \
278 } while (0)
279
280/**
281 * Macro for initializing a DBGC variable with a GC flat address.
282 */
283#define DBGCVAR_INIT_GC_FLAT(pVar, Flat) \
284 do { \
285 DBGCVAR_INIT(pVar); \
286 (pVar)->enmType = DBGCVAR_TYPE_GC_FLAT; \
287 (pVar)->u.GCFlat = (Flat); \
288 } while (0)
289
290/**
291 * Macro for initializing a DBGC variable with a GC flat address.
292 */
293#define DBGCVAR_INIT_GC_FLAT_BYTE_RANGE(pVar, Flat, cbRange) \
294 do { \
295 DBGCVAR_INIT(pVar); \
296 (pVar)->enmType = DBGCVAR_TYPE_GC_FLAT; \
297 (pVar)->u.GCFlat = (Flat); \
298 DBGCVAR_SET_RANGE(pVar, DBGCVAR_RANGE_BYTES, cbRange); \
299 } while (0)
300
301/**
302 * Macro for initializing a DBGC variable with a GC far address.
303 */
304#define DBGCVAR_INIT_GC_FAR(pVar, _sel, _off) \
305 do { \
306 DBGCVAR_INIT(pVar); \
307 (pVar)->enmType = DBGCVAR_TYPE_GC_FAR; \
308 (pVar)->u.GCFar.sel = (_sel); \
309 (pVar)->u.GCFar.off = (_off); \
310 } while (0)
311
312/**
313 * Macro for initializing a DBGC variable with a number.
314 */
315#define DBGCVAR_INIT_NUMBER(pVar, Value) \
316 do { \
317 DBGCVAR_INIT(pVar); \
318 (pVar)->enmType = DBGCVAR_TYPE_NUMBER; \
319 (pVar)->u.u64Number = (Value); \
320 } while (0)
321
322/**
323 * Macro for initializing a DBGC variable with a string.
324 */
325#define DBGCVAR_INIT_STRING(pVar, a_pszString) \
326 do { \
327 DBGCVAR_INIT(pVar); \
328 (pVar)->enmType = DBGCVAR_TYPE_STRING; \
329 (pVar)->enmRangeType = DBGCVAR_RANGE_BYTES; \
330 (pVar)->u.pszString = (a_pszString); \
331 (pVar)->u64Range = strlen(a_pszString); \
332 } while (0)
333
334
335/**
336 * Macro for initializing a DBGC variable with a symbol.
337 */
338#define DBGCVAR_INIT_SYMBOL(pVar, a_pszSymbol) \
339 do { \
340 DBGCVAR_INIT(pVar); \
341 (pVar)->enmType = DBGCVAR_TYPE_SYMBOL; \
342 (pVar)->enmRangeType = DBGCVAR_RANGE_BYTES; \
343 (pVar)->u.pszString = (a_pszSymbol); \
344 (pVar)->u64Range = strlen(a_pszSymbol); \
345 } while (0)
346
347
348/**
349 * Macro for setting the range of a DBGC variable.
350 * @param pVar The variable.
351 * @param _enmRangeType The range type.
352 * @param Value The range length value.
353 */
354#define DBGCVAR_SET_RANGE(pVar, _enmRangeType, Value) \
355 do { \
356 (pVar)->enmRangeType = (_enmRangeType); \
357 (pVar)->u64Range = (Value); \
358 } while (0)
359
360
361/**
362 * Macro for setting the range of a DBGC variable.
363 * @param a_pVar The variable.
364 * @param a_cbRange The range, in bytes.
365 */
366#define DBGCVAR_SET_BYTE_RANGE(a_pVar, a_cbRange) \
367 DBGCVAR_SET_RANGE(a_pVar, DBGCVAR_RANGE_BYTES, a_cbRange)
368
369
370/**
371 * Macro for resetting the range a DBGC variable.
372 * @param a_pVar The variable.
373 */
374#define DBGCVAR_ZAP_RANGE(a_pVar) \
375 do { \
376 (a_pVar)->enmRangeType = DBGCVAR_RANGE_NONE; \
377 (a_pVar)->u64Range = 0; \
378 } while (0)
379
380
381/**
382 * Macro for assigning one DBGC variable to another.
383 * @param a_pResult The result (target) variable.
384 * @param a_pVar The source variable.
385 */
386#define DBGCVAR_ASSIGN(a_pResult, a_pVar) \
387 do { \
388 *(a_pResult) = *(a_pVar); \
389 } while (0)
390
391
392/** Pointer to a command descriptor. */
393typedef struct DBGCCMD *PDBGCCMD;
394/** Pointer to a const command descriptor. */
395typedef const struct DBGCCMD *PCDBGCCMD;
396
397/** Pointer to a function descriptor. */
398typedef struct DBGCFUNC *PDBGCFUNC;
399/** Pointer to a const function descriptor. */
400typedef const struct DBGCFUNC *PCDBGCFUNC;
401
402/** Pointer to helper functions for commands. */
403typedef struct DBGCCMDHLP *PDBGCCMDHLP;
404
405
406/**
407 * Helper functions for commands.
408 */
409typedef struct DBGCCMDHLP
410{
411 /** Magic value (DBGCCMDHLP_MAGIC). */
412 uint32_t u32Magic;
413
414 /**
415 * Command helper for writing formatted text to the debug console.
416 *
417 * @returns VBox status.
418 * @param pCmdHlp Pointer to the command callback structure.
419 * @param pcbWritten Where to store the number of bytes written.
420 * This is optional.
421 * @param pszFormat The format string. This may use all IPRT extensions as
422 * well as the debugger ones.
423 * @param ... Arguments specified in the format string.
424 */
425 DECLCALLBACKMEMBER(int, pfnPrintf,(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten,
426 const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(3, 4);
427
428 /**
429 * Command helper for writing formatted text to the debug console.
430 *
431 * @returns VBox status.
432 * @param pCmdHlp Pointer to the command callback structure.
433 * @param pcbWritten Where to store the number of bytes written.
434 * This is optional.
435 * @param pszFormat The format string. This may use all IPRT extensions as
436 * well as the debugger ones.
437 * @param args Arguments specified in the format string.
438 */
439 DECLCALLBACKMEMBER(int, pfnPrintfV,(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten,
440 const char *pszFormat, va_list args)) RT_IPRT_FORMAT_ATTR(3, 0);
441
442 /**
443 * Command helper for formatting a string with debugger format specifiers.
444 *
445 * @returns The number of bytes written.
446 * @param pCmdHlp Pointer to the command callback structure.
447 * @param pszBuf The output buffer.
448 * @param cbBuf The size of the output buffer.
449 * @param pszFormat The format string. This may use all IPRT extensions as
450 * well as the debugger ones.
451 * @param ... Arguments specified in the format string.
452 */
453 DECLCALLBACKMEMBER(size_t, pfnStrPrintf,(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
454 const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(4, 5);
455
456 /**
457 * Command helper for formatting a string with debugger format specifiers.
458 *
459 * @returns The number of bytes written.
460 * @param pCmdHlp Pointer to the command callback structure.
461 * @param pszBuf The output buffer.
462 * @param cbBuf The size of the output buffer.
463 * @param pszFormat The format string. This may use all IPRT extensions as
464 * well as the debugger ones.
465 * @param va Arguments specified in the format string.
466 */
467 DECLCALLBACKMEMBER(size_t, pfnStrPrintfV,(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
468 const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(4, 0);
469
470 /**
471 * Command helper for formatting and error message for a VBox status code.
472 *
473 * @returns VBox status code appropriate to return from a command.
474 * @param pCmdHlp Pointer to the command callback structure.
475 * @param rc The VBox status code.
476 * @param pszFormat Format string for additional messages. Can be NULL.
477 * @param ... Format arguments, optional.
478 */
479 DECLCALLBACKMEMBER(int, pfnVBoxError,(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(3, 4);
480
481 /**
482 * Command helper for formatting and error message for a VBox status code.
483 *
484 * @returns VBox status code appropriate to return from a command.
485 * @param pCmdHlp Pointer to the command callback structure.
486 * @param rc The VBox status code.
487 * @param pszFormat Format string for additional messages. Can be NULL.
488 * @param args Format arguments, optional.
489 */
490 DECLCALLBACKMEMBER(int, pfnVBoxErrorV,(PDBGCCMDHLP pCmdHlp, int rc,
491 const char *pszFormat, va_list args)) RT_IPRT_FORMAT_ATTR(3, 0);
492
493 /**
494 * Command helper for reading memory specified by a DBGC variable.
495 *
496 * @returns VBox status code appropriate to return from a command.
497 * @param pCmdHlp Pointer to the command callback structure.
498 * @param pvBuffer Where to store the read data.
499 * @param cbRead Number of bytes to read.
500 * @param pVarPointer DBGC variable specifying where to start reading.
501 * @param pcbRead Where to store the number of bytes actually read.
502 * This optional, but it's useful when read GC virtual memory where a
503 * page in the requested range might not be present.
504 * If not specified not-present failure or end of a HC physical page
505 * will cause failure.
506 */
507 DECLCALLBACKMEMBER(int, pfnMemRead,(PDBGCCMDHLP pCmdHlp, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead));
508
509 /**
510 * Command helper for writing memory specified by a DBGC variable.
511 *
512 * @returns VBox status code appropriate to return from a command.
513 * @param pCmdHlp Pointer to the command callback structure.
514 * @param pvBuffer What to write.
515 * @param cbWrite Number of bytes to write.
516 * @param pVarPointer DBGC variable specifying where to start reading.
517 * @param pcbWritten Where to store the number of bytes written.
518 * This is optional. If NULL be aware that some of the buffer
519 * might have been written to the specified address.
520 */
521 DECLCALLBACKMEMBER(int, pfnMemWrite,(PDBGCCMDHLP pCmdHlp, const void *pvBuffer, size_t cbWrite, PCDBGCVAR pVarPointer, size_t *pcbWritten));
522
523 /**
524 * Executes command an expression.
525 * (Hopefully the parser and functions are fully reentrant.)
526 *
527 * @returns VBox status code appropriate to return from a command.
528 * @param pCmdHlp Pointer to the command callback structure.
529 * @param pszExpr The expression. Format string with the format DBGC extensions.
530 * @param ... Format arguments.
531 */
532 DECLCALLBACKMEMBER(int, pfnExec,(PDBGCCMDHLP pCmdHlp, const char *pszExpr, ...)) RT_IPRT_FORMAT_ATTR(2, 3);
533
534 /**
535 * Evaluates an expression.
536 * (Hopefully the parser and functions are fully reentrant.)
537 *
538 * @returns VBox status code appropriate to return from a command.
539 * @param pCmdHlp Pointer to the command callback structure.
540 * @param pResult Where to store the result.
541 * @param pszExpr The expression. Format string with the format DBGC extensions.
542 * @param va Format arguments.
543 */
544 DECLCALLBACKMEMBER(int, pfnEvalV,(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult,
545 const char *pszExpr, va_list va)) RT_IPRT_FORMAT_ATTR(3, 0);
546
547 /**
548 * Print an error and fail the current command.
549 *
550 * @returns VBox status code to pass upwards.
551 *
552 * @param pCmdHlp Pointer to the command callback structure.
553 * @param pCmd The failing command.
554 * @param pszFormat The error message format string.
555 * @param va Format arguments.
556 */
557 DECLCALLBACKMEMBER(int, pfnFailV,(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd,
558 const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(3, 0);
559
560 /**
561 * Print an error and fail the current command.
562 *
563 * @returns VBox status code to pass upwards.
564 *
565 * @param pCmdHlp Pointer to the command callback structure.
566 * @param pCmd The failing command.
567 * @param rc The status code indicating the failure. This will
568 * be appended to the message after a colon (': ').
569 * @param pszFormat The error message format string.
570 * @param va Format arguments.
571 *
572 * @see DBGCCmdHlpFailRc
573 */
574 DECLCALLBACKMEMBER(int, pfnFailRcV,(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int rc,
575 const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(4, 0);
576
577 /**
578 * Parser error.
579 *
580 * @returns VBox status code to pass upwards.
581 *
582 * @param pCmdHlp Pointer to the command callback structure.
583 * @param pCmd The failing command, can be NULL but shouldn't.
584 * @param iArg The offending argument, -1 when lazy.
585 * @param pszExpr The expression.
586 * @param iLine The line number.
587 */
588 DECLCALLBACKMEMBER(int, pfnParserError,(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int iArg, const char *pszExpr, unsigned iLine));
589
590 /**
591 * Converts a DBGC variable to a DBGF address structure.
592 *
593 * @returns VBox status code.
594 * @param pCmdHlp Pointer to the command callback structure.
595 * @param pVar The variable to convert.
596 * @param pAddress The target address.
597 */
598 DECLCALLBACKMEMBER(int, pfnVarToDbgfAddr,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress));
599
600 /**
601 * Converts a DBGF address structure to a DBGC variable.
602 *
603 * @returns VBox status code.
604 * @param pCmdHlp Pointer to the command callback structure.
605 * @param pAddress The source address.
606 * @param pResult The result variable.
607 */
608 DECLCALLBACKMEMBER(int, pfnVarFromDbgfAddr,(PDBGCCMDHLP pCmdHlp, PCDBGFADDRESS pAddress, PDBGCVAR pResult));
609
610 /**
611 * Converts a DBGC variable to a 64-bit number.
612 *
613 * @returns VBox status code.
614 * @param pCmdHlp Pointer to the command callback structure.
615 * @param pVar The variable to convert.
616 * @param pu64Number Where to store the number.
617 */
618 DECLCALLBACKMEMBER(int, pfnVarToNumber,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t *pu64Number));
619
620 /**
621 * Converts a DBGC variable to a boolean.
622 *
623 * @returns VBox status code.
624 * @param pCmdHlp Pointer to the command callback structure.
625 * @param pVar The variable to convert.
626 * @param pf Where to store the boolean.
627 */
628 DECLCALLBACKMEMBER(int, pfnVarToBool,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf));
629
630 /**
631 * Get the range of a variable in bytes, resolving symbols if necessary.
632 *
633 * @returns VBox status code.
634 * @param pCmdHlp Pointer to the command callback structure.
635 * @param pVar The variable to convert.
636 * @param cbElement Conversion factor for element ranges.
637 * @param cbDefault The default range.
638 * @param pcbRange The length of the range.
639 */
640 DECLCALLBACKMEMBER(int, pfnVarGetRange,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t cbElement, uint64_t cbDefault,
641 uint64_t *pcbRange));
642
643 /**
644 * Converts a variable to one with the specified type.
645 *
646 * This preserves the range.
647 *
648 * @returns VBox status code.
649 * @param pCmdHlp Pointer to the command callback structure.
650 * @param pVar The variable to convert.
651 * @param enmToType The target type.
652 * @param fConvSyms If @c true, then attempt to resolve symbols.
653 * @param pResult The output variable. Can be the same as @a pVar.
654 */
655 DECLCALLBACKMEMBER(int, pfnVarConvert,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, DBGCVARTYPE enmToType, bool fConvSyms,
656 PDBGCVAR pResult));
657
658 /**
659 * Gets a DBGF output helper that directs the output to the debugger
660 * console.
661 *
662 * @returns Pointer to the helper structure.
663 * @param pCmdHlp Pointer to the command callback structure.
664 */
665 DECLCALLBACKMEMBER(PCDBGFINFOHLP, pfnGetDbgfOutputHlp,(PDBGCCMDHLP pCmdHlp));
666
667 /**
668 * Gets the ID currently selected CPU.
669 *
670 * @returns Current CPU ID.
671 * @param pCmdHlp Pointer to the command callback structure.
672 */
673 DECLCALLBACKMEMBER(VMCPUID, pfnGetCurrentCpu,(PDBGCCMDHLP pCmdHlp));
674
675 /**
676 * Gets the mode the currently selected CPU is running in, in the current
677 * context.
678 *
679 * @returns Current CPU mode.
680 * @param pCmdHlp Pointer to the command callback structure.
681 */
682 DECLCALLBACKMEMBER(CPUMMODE, pfnGetCpuMode,(PDBGCCMDHLP pCmdHlp));
683
684 /**
685 * Prints the register set of the given CPU.
686 *
687 * @returns VBox status code.
688 * @param pCmdHlp Pointer to the command callback structure.
689 * @param idCpu The CPU ID to print the register set of.
690 * @param f64BitMode True to dump 64-bit state, false to dump 32-bit state,
691 * -1 to use the current CPU mode.
692 * @param fTerse Flag to indicate whether to dump the complete register set.
693 */
694 DECLCALLBACKMEMBER(int, pfnRegPrintf, (PDBGCCMDHLP pCmdHlp, VMCPUID idCpu, int f64BitMode, bool fTerse));
695
696 /** End marker (DBGCCMDHLP_MAGIC). */
697 uint32_t u32EndMarker;
698} DBGCCMDHLP;
699
700/** Magic value for DBGCCMDHLP::u32Magic. (Fyodor Mikhaylovich Dostoyevsky) */
701#define DBGCCMDHLP_MAGIC UINT32_C(18211111)
702
703
704#if defined(IN_RING3) || defined(IN_SLICKEDIT)
705
706/**
707 * Command helper for writing formatted text to the debug console.
708 *
709 * @returns VBox status.
710 * @param pCmdHlp Pointer to the command callback structure.
711 * @param pszFormat The format string. This may use all IPRT extensions as
712 * well as the debugger ones.
713 * @param ... Arguments specified in the format string.
714 */
715DECLINLINE(int) RT_IPRT_FORMAT_ATTR(2, 3) DBGCCmdHlpPrintf(PDBGCCMDHLP pCmdHlp, const char *pszFormat, ...)
716{
717 va_list va;
718 int rc;
719
720 va_start(va, pszFormat);
721 rc = pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, va);
722 va_end(va);
723
724 return rc;
725}
726
727/**
728 * Command helper for writing formatted text to the debug console.
729 *
730 * @returns VBox status.
731 * @param pCmdHlp Pointer to the command callback structure.
732 * @param pcbWritten Where to store the amount of written characters on success.
733 * @param pszFormat The format string. This may use all IPRT extensions as
734 * well as the debugger ones.
735 * @param ... Arguments specified in the format string.
736 */
737DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpPrintfEx(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten,
738 const char *pszFormat, ...)
739{
740 va_list va;
741 int rc;
742
743 va_start(va, pszFormat);
744 rc = pCmdHlp->pfnPrintfV(pCmdHlp, pcbWritten, pszFormat, va);
745 va_end(va);
746
747 return rc;
748}
749
750/**
751 * Command helper for writing formatted text to the debug console.
752 *
753 * @returns Number of bytes written.
754 * @param pCmdHlp Pointer to the command callback structure.
755 * @param pszFormat The format string. This may use all IPRT extensions as
756 * well as the debugger ones.
757 * @param ... Arguments specified in the format string.
758 */
759DECLINLINE(size_t) RT_IPRT_FORMAT_ATTR(2, 3) DBGCCmdHlpPrintfLen(PDBGCCMDHLP pCmdHlp, const char *pszFormat, ...)
760{
761 va_list va;
762 int rc;
763 size_t cbWritten = 0;
764
765 va_start(va, pszFormat);
766 rc = pCmdHlp->pfnPrintfV(pCmdHlp, &cbWritten, pszFormat, va);
767 va_end(va);
768
769 return RT_SUCCESS(rc) ? cbWritten : 0;
770}
771
772/**
773 * @copydoc DBGCCMDHLP::pfnStrPrintf
774 */
775DECLINLINE(size_t) RT_IPRT_FORMAT_ATTR(4, 5) DBGCCmdHlpStrPrintf(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
776 const char *pszFormat, ...)
777{
778 va_list va;
779 size_t cch;
780
781 va_start(va, pszFormat);
782 cch = pCmdHlp->pfnStrPrintfV(pCmdHlp, pszBuf, cbBuf, pszFormat, va);
783 va_end(va);
784
785 return cch;
786}
787
788/**
789 * @copydoc DBGCCMDHLP::pfnVBoxError
790 */
791DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpVBoxError(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)
792{
793 va_list va;
794
795 va_start(va, pszFormat);
796 rc = pCmdHlp->pfnVBoxErrorV(pCmdHlp, rc, pszFormat, va);
797 va_end(va);
798
799 return rc;
800}
801
802/**
803 * @copydoc DBGCCMDHLP::pfnMemRead
804 */
805DECLINLINE(int) DBGCCmdHlpMemRead(PDBGCCMDHLP pCmdHlp, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead)
806{
807 return pCmdHlp->pfnMemRead(pCmdHlp, pvBuffer, cbRead, pVarPointer, pcbRead);
808}
809
810/**
811 * Evaluates an expression.
812 * (Hopefully the parser and functions are fully reentrant.)
813 *
814 * @returns VBox status code appropriate to return from a command.
815 * @param pCmdHlp Pointer to the command callback structure.
816 * @param pResult Where to store the result.
817 * @param pszExpr The expression. Format string with the format DBGC extensions.
818 * @param ... Format arguments.
819 */
820DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpEval(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult, const char *pszExpr, ...)
821{
822 va_list va;
823 int rc;
824
825 va_start(va, pszExpr);
826 rc = pCmdHlp->pfnEvalV(pCmdHlp, pResult, pszExpr, va);
827 va_end(va);
828
829 return rc;
830}
831
832/**
833 * Print an error and fail the current command.
834 *
835 * @returns VBox status code to pass upwards.
836 *
837 * @param pCmdHlp Pointer to the command callback structure.
838 * @param pCmd The failing command.
839 * @param pszFormat The error message format string.
840 * @param ... Format arguments.
841 */
842DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpFail(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, const char *pszFormat, ...)
843{
844 va_list va;
845 int rc;
846
847 va_start(va, pszFormat);
848 rc = pCmdHlp->pfnFailV(pCmdHlp, pCmd, pszFormat, va);
849 va_end(va);
850
851 return rc;
852}
853
854/**
855 * Print an error and fail the current command.
856 *
857 * Usage example:
858 * @code
859 int rc = VMMR3Something(pVM);
860 if (RT_FAILURE(rc))
861 return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "VMMR3Something");
862 return VINF_SUCCESS;
863 * @endcode
864 *
865 * @returns VBox status code to pass upwards.
866 *
867 * @param pCmdHlp Pointer to the command callback structure.
868 * @param pCmd The failing command.
869 * @param rc The status code indicating the failure.
870 * @param pszFormat The error message format string.
871 * @param ... Format arguments.
872 */
873DECLINLINE(int) RT_IPRT_FORMAT_ATTR(4, 5) DBGCCmdHlpFailRc(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int rc,
874 const char *pszFormat, ...)
875{
876 va_list va;
877
878 va_start(va, pszFormat);
879 rc = pCmdHlp->pfnFailRcV(pCmdHlp, pCmd, rc, pszFormat, va);
880 va_end(va);
881
882 return rc;
883}
884
885/**
886 * @copydoc DBGCCMDHLP::pfnParserError
887 */
888DECLINLINE(int) DBGCCmdHlpParserError(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int iArg, const char *pszExpr, unsigned iLine)
889{
890 return pCmdHlp->pfnParserError(pCmdHlp, pCmd, iArg, pszExpr, iLine);
891}
892
893/** Assert+return like macro for checking parser sanity.
894 * Returns with failure if the precodition is not met. */
895#define DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, iArg, expr) \
896 do { \
897 if (!(expr)) \
898 return DBGCCmdHlpParserError(pCmdHlp, pCmd, iArg, #expr, __LINE__); \
899 } while (0)
900
901/** Assert+return like macro that the VM handle is present.
902 * Returns with failure if the VM handle is NIL. */
903#define DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM) \
904 do { \
905 if (!(pUVM)) \
906 return DBGCCmdHlpFail(pCmdHlp, pCmd, "No VM selected"); \
907 } while (0)
908
909/**
910 * @copydoc DBGCCMDHLP::pfnVarToDbgfAddr
911 */
912DECLINLINE(int) DBGCCmdHlpVarToDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
913{
914 return pCmdHlp->pfnVarToDbgfAddr(pCmdHlp, pVar, pAddress);
915}
916
917/**
918 * @copydoc DBGCCMDHLP::pfnVarFromDbgfAddr
919 */
920DECLINLINE(int) DBGCCmdHlpVarFromDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGFADDRESS pAddress, PDBGCVAR pResult)
921{
922 return pCmdHlp->pfnVarFromDbgfAddr(pCmdHlp, pAddress, pResult);
923}
924
925/**
926 * Converts an variable to a flat address.
927 *
928 * @returns VBox status code.
929 * @param pCmdHlp Pointer to the command callback structure.
930 * @param pVar The variable to convert.
931 * @param pFlatPtr Where to store the flat address.
932 */
933DECLINLINE(int) DBGCCmdHlpVarToFlatAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PRTGCPTR pFlatPtr)
934{
935 DBGFADDRESS Addr;
936 int rc = pCmdHlp->pfnVarToDbgfAddr(pCmdHlp, pVar, &Addr);
937 if (RT_SUCCESS(rc))
938 *pFlatPtr = Addr.FlatPtr;
939 return rc;
940}
941
942/**
943 * @copydoc DBGCCMDHLP::pfnVarToNumber
944 */
945DECLINLINE(int) DBGCCmdHlpVarToNumber(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t *pu64Number)
946{
947 return pCmdHlp->pfnVarToNumber(pCmdHlp, pVar, pu64Number);
948}
949
950/**
951 * @copydoc DBGCCMDHLP::pfnVarToBool
952 */
953DECLINLINE(int) DBGCCmdHlpVarToBool(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf)
954{
955 return pCmdHlp->pfnVarToBool(pCmdHlp, pVar, pf);
956}
957
958/**
959 * @copydoc DBGCCMDHLP::pfnVarGetRange
960 */
961DECLINLINE(int) DBGCCmdHlpVarGetRange(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t cbElement, uint64_t cbDefault, uint64_t *pcbRange)
962{
963 return pCmdHlp->pfnVarGetRange(pCmdHlp, pVar, cbElement, cbDefault, pcbRange);
964}
965
966/**
967 * @copydoc DBGCCMDHLP::pfnVarConvert
968 */
969DECLINLINE(int) DBGCCmdHlpConvert(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, DBGCVARTYPE enmToType, bool fConvSyms, PDBGCVAR pResult)
970{
971 return pCmdHlp->pfnVarConvert(pCmdHlp, pVar, enmToType, fConvSyms, pResult);
972}
973
974/**
975 * @copydoc DBGCCMDHLP::pfnGetDbgfOutputHlp
976 */
977DECLINLINE(PCDBGFINFOHLP) DBGCCmdHlpGetDbgfOutputHlp(PDBGCCMDHLP pCmdHlp)
978{
979 return pCmdHlp->pfnGetDbgfOutputHlp(pCmdHlp);
980}
981
982/**
983 * @copydoc DBGCCMDHLP::pfnGetCurrentCpu
984 */
985DECLINLINE(VMCPUID) DBGCCmdHlpGetCurrentCpu(PDBGCCMDHLP pCmdHlp)
986{
987 return pCmdHlp->pfnGetCurrentCpu(pCmdHlp);
988}
989
990/**
991 * @copydoc DBGCCMDHLP::pfnGetCpuMode
992 */
993DECLINLINE(CPUMMODE) DBGCCmdHlpGetCpuMode(PDBGCCMDHLP pCmdHlp)
994{
995 return pCmdHlp->pfnGetCpuMode(pCmdHlp);
996}
997
998/**
999 * @copydoc DBGCCMDHLP::pfnRegPrintf
1000 */
1001DECLINLINE(int) DBGCCmdHlpRegPrintf(PDBGCCMDHLP pCmdHlp, VMCPUID idCpu, int f64BitMode, bool fTerse)
1002{
1003 return pCmdHlp->pfnRegPrintf(pCmdHlp, idCpu, f64BitMode, fTerse);
1004}
1005
1006#endif /* IN_RING3 */
1007
1008
1009
1010/**
1011 * Command handler.
1012 *
1013 * The console will call the handler for a command once it's finished
1014 * parsing the user input. The command handler function is responsible
1015 * for executing the command itself.
1016 *
1017 * @returns VBox status.
1018 * @param pCmd Pointer to the command descriptor (as registered).
1019 * @param pCmdHlp Pointer to command helper functions.
1020 * @param pUVM The user mode VM handle, can in theory be NULL.
1021 * @param paArgs Pointer to (readonly) array of arguments.
1022 * @param cArgs Number of arguments in the array.
1023 */
1024typedef DECLCALLBACKTYPE(int, FNDBGCCMD,(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs));
1025/** Pointer to a FNDBGCCMD() function. */
1026typedef FNDBGCCMD *PFNDBGCCMD;
1027
1028/**
1029 * DBGC command descriptor.
1030 */
1031typedef struct DBGCCMD
1032{
1033 /** Command string. */
1034 const char *pszCmd;
1035 /** Minimum number of arguments. */
1036 unsigned cArgsMin;
1037 /** Max number of arguments. */
1038 unsigned cArgsMax;
1039 /** Argument descriptors (array). */
1040 PCDBGCVARDESC paArgDescs;
1041 /** Number of argument descriptors. */
1042 unsigned cArgDescs;
1043 /** flags. (reserved for now) */
1044 unsigned fFlags;
1045 /** Handler function. */
1046 PFNDBGCCMD pfnHandler;
1047 /** Command syntax. */
1048 const char *pszSyntax;
1049 /** Command description. */
1050 const char *pszDescription;
1051} DBGCCMD;
1052
1053/** DBGCCMD Flags.
1054 * @{
1055 */
1056/** @} */
1057
1058
1059/**
1060 * Function handler.
1061 *
1062 * The console will call the handler for a command once it's finished
1063 * parsing the user input. The command handler function is responsible
1064 * for executing the command itself.
1065 *
1066 * @returns VBox status.
1067 * @param pFunc Pointer to the function descriptor (as registered).
1068 * @param pCmdHlp Pointer to command helper functions.
1069 * @param pUVM The user mode VM handle, can in theory be NULL.
1070 * @param paArgs Pointer to (readonly) array of arguments.
1071 * @param cArgs Number of arguments in the array.
1072 * @param pResult Where to return the result.
1073 */
1074typedef DECLCALLBACKTYPE(int, FNDBGCFUNC,(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs,
1075 PDBGCVAR pResult));
1076/** Pointer to a FNDBGCFUNC() function. */
1077typedef FNDBGCFUNC *PFNDBGCFUNC;
1078
1079/**
1080 * DBGC function descriptor.
1081 */
1082typedef struct DBGCFUNC
1083{
1084 /** Command string. */
1085 const char *pszFuncNm;
1086 /** Minimum number of arguments. */
1087 unsigned cArgsMin;
1088 /** Max number of arguments. */
1089 unsigned cArgsMax;
1090 /** Argument descriptors (array). */
1091 PCDBGCVARDESC paArgDescs;
1092 /** Number of argument descriptors. */
1093 unsigned cArgDescs;
1094 /** flags. (reserved for now) */
1095 unsigned fFlags;
1096 /** Handler function. */
1097 PFNDBGCFUNC pfnHandler;
1098 /** Function syntax. */
1099 const char *pszSyntax;
1100 /** Function description. */
1101 const char *pszDescription;
1102} DBGCFUNC;
1103
1104
1105/** Pointer to a const I/O callback table. */
1106typedef const struct DBGCIO *PCDBGCIO;
1107
1108/**
1109 * I/O callback table.
1110 */
1111typedef struct DBGCIO
1112{
1113 /**
1114 * Destroys the given I/O instance.
1115 *
1116 * @returns nothing.
1117 * @param pIo Pointer to the I/O structure supplied by the I/O provider.
1118 */
1119 DECLCALLBACKMEMBER(void, pfnDestroy, (PCDBGCIO pIo));
1120
1121 /**
1122 * Wait for input available for reading.
1123 *
1124 * @returns Flag whether there is input ready upon return.
1125 * @retval true if there is input ready.
1126 * @retval false if there not input ready.
1127 * @param pIo Pointer to the I/O structure supplied by
1128 * the I/O provider. The backend can use this to find it's instance data.
1129 * @param cMillies Number of milliseconds to wait on input data.
1130 */
1131 DECLCALLBACKMEMBER(bool, pfnInput, (PCDBGCIO pIo, uint32_t cMillies));
1132
1133 /**
1134 * Read input.
1135 *
1136 * @returns VBox status code.
1137 * @param pIo Pointer to the I/O structure supplied by
1138 * the I/O provider. The backend can use this to find it's instance data.
1139 * @param pvBuf Where to put the bytes we read.
1140 * @param cbBuf Maximum nymber of bytes to read.
1141 * @param pcbRead Where to store the number of bytes actually read.
1142 * If NULL the entire buffer must be filled for a
1143 * successful return.
1144 */
1145 DECLCALLBACKMEMBER(int, pfnRead, (PCDBGCIO pIo, void *pvBuf, size_t cbBuf, size_t *pcbRead));
1146
1147 /**
1148 * Write (output).
1149 *
1150 * @returns VBox status code.
1151 * @param pIo Pointer to the I/O structure supplied by
1152 * the I/O provider. The backend can use this to find it's instance data.
1153 * @param pvBuf What to write.
1154 * @param cbBuf Number of bytes to write.
1155 * @param pcbWritten Where to store the number of bytes actually written.
1156 * If NULL the entire buffer must be successfully written.
1157 */
1158 DECLCALLBACKMEMBER(int, pfnWrite, (PCDBGCIO pIo, const void *pvBuf, size_t cbBuf, size_t *pcbWritten));
1159
1160 /**
1161 * Ready / busy notification.
1162 *
1163 * @returns nothing.
1164 * @param pIo Pointer to the I/O structure supplied by
1165 * the I/O provider. The backend can use this to find it's instance data.
1166 * @param fReady Whether it's ready (true) or busy (false).
1167 */
1168 DECLCALLBACKMEMBER(void, pfnSetReady, (PCDBGCIO pIo, bool fReady));
1169
1170} DBGCIO;
1171/** Pointer to an I/O callback table. */
1172typedef DBGCIO *PDBGCIO;
1173
1174
1175DBGDECL(int) DBGCCreate(PUVM pUVM, PCDBGCIO pIo, unsigned fFlags);
1176DBGDECL(int) DBGCRegisterCommands(PCDBGCCMD paCommands, unsigned cCommands);
1177DBGDECL(int) DBGCDeregisterCommands(PCDBGCCMD paCommands, unsigned cCommands);
1178
1179DBGDECL(int) DBGCIoCreate(PUVM pUVM, void **ppvData);
1180DBGDECL(int) DBGCIoTerminate(PUVM pUVM, void *pvData);
1181
1182/** @} */
1183
1184#endif /* IN_RING3 */
1185
1186/** @} */
1187RT_C_DECLS_END
1188
1189#endif /* !VBOX_INCLUDED_dbg_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