summaryrefslogtreecommitdiffstats
path: root/include/VBox/dbg.h
blob: 901b72da47b004c0d94f6cecc0dfd691c3f19623 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
/** @file
 * Debugger Interfaces. (VBoxDbg)
 *
 * This header covers all external interfaces of the Debugger module.
 * However, it does not cover the DBGF interface since that part of the
 * VMM. Use dbgf.h for that.
 */

/*
 * Copyright (C) 2006-2022 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
 * in the VirtualBox distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 *
 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
 */

#ifndef VBOX_INCLUDED_dbg_h
#define VBOX_INCLUDED_dbg_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#include <VBox/cdefs.h>
#include <VBox/types.h>
#include <VBox/vmm/dbgf.h>

#include <iprt/stdarg.h>
#ifdef IN_RING3
# include <iprt/errcore.h>
#endif

RT_C_DECLS_BEGIN



/** @defgroup grp_dbg       The VirtualBox Debugger
 * @{
 */

#ifdef IN_RING3 /* The debugger stuff is ring-3 only. */

/** @defgroup grp_dbgc     The Debugger Console API
 * @{
 */

/** @def VBOX_WITH_DEBUGGER
 * The build is with debugger module. Test if this is defined before registering
 * external debugger commands. This is normally defined in Config.kmk.
 */
#ifdef DOXYGEN_RUNNING
# define VBOX_WITH_DEBUGGER
#endif


/**
 * DBGC variable category.
 *
 * Used to describe an argument to a command or function and a functions
 * return value.
 */
typedef enum DBGCVARCAT
{
    /** Any type is fine. */
    DBGCVAR_CAT_ANY = 0,
    /** Any kind of pointer or number. */
    DBGCVAR_CAT_POINTER_NUMBER,
    /** Any kind of pointer or number, no range. */
    DBGCVAR_CAT_POINTER_NUMBER_NO_RANGE,
    /** Any kind of pointer. */
    DBGCVAR_CAT_POINTER,
    /** Any kind of pointer with no range option. */
    DBGCVAR_CAT_POINTER_NO_RANGE,
    /** GC pointer. */
    DBGCVAR_CAT_GC_POINTER,
    /** GC pointer with no range option. */
    DBGCVAR_CAT_GC_POINTER_NO_RANGE,
    /** Numeric argument. */
    DBGCVAR_CAT_NUMBER,
    /** Numeric argument with no range option. */
    DBGCVAR_CAT_NUMBER_NO_RANGE,
    /** String. */
    DBGCVAR_CAT_STRING,
    /** Symbol. */
    DBGCVAR_CAT_SYMBOL,
    /** Option. */
    DBGCVAR_CAT_OPTION,
    /** Option + string. */
    DBGCVAR_CAT_OPTION_STRING,
    /** Option + number. */
    DBGCVAR_CAT_OPTION_NUMBER
} DBGCVARCAT;


/**
 * DBGC variable type.
 */
typedef enum DBGCVARTYPE
{
    /** unknown... */
    DBGCVAR_TYPE_UNKNOWN = 0,
    /** Flat GC pointer. */
    DBGCVAR_TYPE_GC_FLAT,
    /** Segmented GC pointer. */
    DBGCVAR_TYPE_GC_FAR,
    /** Physical GC pointer. */
    DBGCVAR_TYPE_GC_PHYS,
    /** Flat HC pointer. */
    DBGCVAR_TYPE_HC_FLAT,
    /** Physical HC pointer. */
    DBGCVAR_TYPE_HC_PHYS,
    /** Number. */
    DBGCVAR_TYPE_NUMBER,
    /** String. */
    DBGCVAR_TYPE_STRING,
    /** Symbol. */
    DBGCVAR_TYPE_SYMBOL,
    /** Special type used when querying symbols. */
    DBGCVAR_TYPE_ANY
} DBGCVARTYPE;

/** @todo Rename to DBGCVAR_IS_xyz. */

/** Checks if the specified variable type is of a pointer persuasion. */
#define DBGCVAR_ISPOINTER(enmType)      ((enmType) >= DBGCVAR_TYPE_GC_FLAT && enmType <= DBGCVAR_TYPE_HC_PHYS)
/** Checks if the specified variable type is of a pointer persuasion. */
#define DBGCVAR_IS_FAR_PTR(enmType)     ((enmType) == DBGCVAR_TYPE_GC_FAR)
/** Checks if the specified variable type is of a pointer persuasion and of the guest context sort. */
#define DBGCVAR_ISGCPOINTER(enmType)    ((enmType) >= DBGCVAR_TYPE_GC_FLAT && (enmType) <= DBGCVAR_TYPE_GC_PHYS)
/** Checks if the specified variable type is of a pointer persuasion and of the host context sort. */
#define DBGCVAR_ISHCPOINTER(enmType)    ((enmType) >= DBGCVAR_TYPE_HC_FLAT && (enmType) <= DBGCVAR_TYPE_HC_PHYS)


/**
 * DBGC variable range type.
 */
typedef enum DBGCVARRANGETYPE
{
    /** No range appliable or no range specified. */
    DBGCVAR_RANGE_NONE = 0,
    /** Number of elements. */
    DBGCVAR_RANGE_ELEMENTS,
    /** Number of bytes. */
    DBGCVAR_RANGE_BYTES
} DBGCVARRANGETYPE;


/**
 * Variable descriptor.
 */
typedef struct DBGCVARDESC
{
    /** The minimal number of times this argument may occur.
     * Use 0 here to inidicate that the argument is optional. */
    unsigned    cTimesMin;
    /** Maximum number of occurrences.
     * Use ~0 here to indicate infinite. */
    unsigned    cTimesMax;
    /** Argument category. */
    DBGCVARCAT  enmCategory;
    /** Flags, DBGCVD_FLAGS_* */
    unsigned    fFlags;
    /** Argument name. */
    const char *pszName;
    /** Argument name. */
    const char *pszDescription;
} DBGCVARDESC;
/** Pointer to an argument descriptor. */
typedef DBGCVARDESC *PDBGCVARDESC;
/** Pointer to a const argument descriptor. */
typedef const DBGCVARDESC *PCDBGCVARDESC;

/** Variable descriptor flags.
 * @{ */
/** Indicates that the variable depends on the previous being present. */
#define DBGCVD_FLAGS_DEP_PREV       RT_BIT(1)
/** @} */


/**
 * DBGC variable.
 */
typedef struct DBGCVAR
{
    /** Pointer to the argument descriptor. */
    PCDBGCVARDESC   pDesc;
    /** Pointer to the next argument. */
    struct DBGCVAR *pNext;

    /** Argument type. */
    DBGCVARTYPE     enmType;
    /** Type specific. */
    union
    {
        /** Flat GC Address.        (DBGCVAR_TYPE_GC_FLAT) */
        RTGCPTR         GCFlat;
        /** Far (16:32) GC Address. (DBGCVAR_TYPE_GC_FAR) */
        RTFAR32         GCFar;
        /** Physical GC Address.    (DBGCVAR_TYPE_GC_PHYS) */
        RTGCPHYS        GCPhys;
        /** Flat HC Address.        (DBGCVAR_TYPE_HC_FLAT) */
        void           *pvHCFlat;
        /** Physical GC Address.    (DBGCVAR_TYPE_HC_PHYS) */
        RTHCPHYS        HCPhys;
        /** String.                 (DBGCVAR_TYPE_STRING)
         * The basic idea is the the this is a pointer to the expression we're
         * parsing, so no messing with freeing. */
        const char     *pszString;
        /** Number.                 (DBGCVAR_TYPE_NUMBER) */
        uint64_t        u64Number;
    } u;

    /** Range type. */
    DBGCVARRANGETYPE    enmRangeType;
    /** Range. The use of the content depends on the enmRangeType. */
    uint64_t            u64Range;
} DBGCVAR;
/** Pointer to a command argument. */
typedef DBGCVAR *PDBGCVAR;
/** Pointer to a const command argument. */
typedef const DBGCVAR *PCDBGCVAR;


/**
 * Macro for initializing a DBGC variable with defaults.
 * The result is an unknown variable type without any range.
 */
#define DBGCVAR_INIT(pVar) \
        do { \
            (pVar)->pDesc = NULL;\
            (pVar)->pNext = NULL; \
            (pVar)->enmType = DBGCVAR_TYPE_UNKNOWN; \
            (pVar)->u.u64Number = 0; \
            (pVar)->enmRangeType = DBGCVAR_RANGE_NONE; \
            (pVar)->u64Range = 0; \
        } while (0)

/**
 * Macro for initializing a DBGC variable with a HC physical address.
 */
#define DBGCVAR_INIT_HC_PHYS(pVar, Phys) \
        do { \
            DBGCVAR_INIT(pVar); \
            (pVar)->enmType = DBGCVAR_TYPE_HC_PHYS; \
            (pVar)->u.HCPhys = (Phys); \
        } while (0)

/**
 * Macro for initializing a DBGC variable with a HC flat address.
 */
#define DBGCVAR_INIT_HC_FLAT(pVar, Flat) \
        do { \
            DBGCVAR_INIT(pVar); \
            (pVar)->enmType = DBGCVAR_TYPE_HC_FLAT; \
            (pVar)->u.pvHCFlat = (Flat); \
        } while (0)

/**
 * Macro for initializing a DBGC variable with a GC physical address.
 */
#define DBGCVAR_INIT_GC_PHYS(pVar, Phys) \
        do { \
            DBGCVAR_INIT(pVar); \
            (pVar)->enmType = DBGCVAR_TYPE_GC_PHYS; \
            (pVar)->u.GCPhys = (Phys); \
        } while (0)

/**
 * Macro for initializing a DBGC variable with a GC flat address.
 */
#define DBGCVAR_INIT_GC_FLAT(pVar, Flat) \
        do { \
            DBGCVAR_INIT(pVar); \
            (pVar)->enmType = DBGCVAR_TYPE_GC_FLAT; \
            (pVar)->u.GCFlat = (Flat); \
        } while (0)

/**
 * Macro for initializing a DBGC variable with a GC flat address.
 */
#define DBGCVAR_INIT_GC_FLAT_BYTE_RANGE(pVar, Flat, cbRange) \
        do { \
            DBGCVAR_INIT(pVar); \
            (pVar)->enmType = DBGCVAR_TYPE_GC_FLAT; \
            (pVar)->u.GCFlat = (Flat); \
            DBGCVAR_SET_RANGE(pVar, DBGCVAR_RANGE_BYTES, cbRange); \
        } while (0)

/**
 * Macro for initializing a DBGC variable with a GC far address.
 */
#define DBGCVAR_INIT_GC_FAR(pVar, _sel, _off) \
        do { \
            DBGCVAR_INIT(pVar); \
            (pVar)->enmType = DBGCVAR_TYPE_GC_FAR; \
            (pVar)->u.GCFar.sel = (_sel); \
            (pVar)->u.GCFar.off = (_off); \
        } while (0)

/**
 * Macro for initializing a DBGC variable with a number.
 */
#define DBGCVAR_INIT_NUMBER(pVar, Value) \
        do { \
            DBGCVAR_INIT(pVar); \
            (pVar)->enmType = DBGCVAR_TYPE_NUMBER; \
            (pVar)->u.u64Number = (Value); \
        } while (0)

/**
 * Macro for initializing a DBGC variable with a string.
 */
#define DBGCVAR_INIT_STRING(pVar, a_pszString) \
        do { \
            DBGCVAR_INIT(pVar); \
            (pVar)->enmType      = DBGCVAR_TYPE_STRING; \
            (pVar)->enmRangeType = DBGCVAR_RANGE_BYTES; \
            (pVar)->u.pszString  = (a_pszString); \
            (pVar)->u64Range     = strlen(a_pszString); \
        } while (0)


/**
 * Macro for initializing a DBGC variable with a symbol.
 */
#define DBGCVAR_INIT_SYMBOL(pVar, a_pszSymbol) \
        do { \
            DBGCVAR_INIT(pVar); \
            (pVar)->enmType      = DBGCVAR_TYPE_SYMBOL; \
            (pVar)->enmRangeType = DBGCVAR_RANGE_BYTES; \
            (pVar)->u.pszString  = (a_pszSymbol); \
            (pVar)->u64Range     = strlen(a_pszSymbol); \
        } while (0)


/**
 * Macro for setting the range of a DBGC variable.
 * @param   pVar            The variable.
 * @param   _enmRangeType   The range type.
 * @param   Value           The range length value.
 */
#define DBGCVAR_SET_RANGE(pVar, _enmRangeType, Value) \
    do { \
        (pVar)->enmRangeType = (_enmRangeType); \
        (pVar)->u64Range = (Value); \
    } while (0)


/**
 * Macro for setting the range of a DBGC variable.
 * @param   a_pVar          The variable.
 * @param   a_cbRange       The range, in bytes.
 */
#define DBGCVAR_SET_BYTE_RANGE(a_pVar, a_cbRange) \
    DBGCVAR_SET_RANGE(a_pVar, DBGCVAR_RANGE_BYTES, a_cbRange)


/**
 * Macro for resetting the range a DBGC variable.
 * @param   a_pVar          The variable.
 */
#define DBGCVAR_ZAP_RANGE(a_pVar) \
    do { \
        (a_pVar)->enmRangeType  = DBGCVAR_RANGE_NONE; \
        (a_pVar)->u64Range      = 0; \
    } while (0)


/**
 * Macro for assigning one DBGC variable to another.
 * @param   a_pResult       The result (target) variable.
 * @param   a_pVar          The source variable.
 */
#define DBGCVAR_ASSIGN(a_pResult, a_pVar) \
    do { \
        *(a_pResult) = *(a_pVar); \
    } while (0)


/** Pointer to a command descriptor. */
typedef struct DBGCCMD *PDBGCCMD;
/** Pointer to a const command descriptor. */
typedef const struct DBGCCMD *PCDBGCCMD;

/** Pointer to a function descriptor. */
typedef struct DBGCFUNC *PDBGCFUNC;
/** Pointer to a const function descriptor. */
typedef const struct DBGCFUNC *PCDBGCFUNC;

/** Pointer to helper functions for commands. */
typedef struct DBGCCMDHLP *PDBGCCMDHLP;


/**
 * Helper functions for commands.
 */
typedef struct DBGCCMDHLP
{
    /** Magic value (DBGCCMDHLP_MAGIC). */
    uint32_t                u32Magic;

    /**
     * Command helper for writing formatted text to the debug console.
     *
     * @returns VBox status.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pcbWritten  Where to store the number of bytes written.
     *                      This is optional.
     * @param   pszFormat   The format string.  This may use all IPRT extensions as
     *                      well as the debugger ones.
     * @param   ...         Arguments specified in the format string.
     */
    DECLCALLBACKMEMBER(int, pfnPrintf,(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten,
                                       const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(3, 4);

    /**
     * Command helper for writing formatted text to the debug console.
     *
     * @returns VBox status.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pcbWritten  Where to store the number of bytes written.
     *                      This is optional.
     * @param   pszFormat   The format string.  This may use all IPRT extensions as
     *                      well as the debugger ones.
     * @param   args        Arguments specified in the format string.
     */
    DECLCALLBACKMEMBER(int, pfnPrintfV,(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten,
                                        const char *pszFormat, va_list args)) RT_IPRT_FORMAT_ATTR(3, 0);

    /**
     * Command helper for formatting a string with debugger format specifiers.
     *
     * @returns The number of bytes written.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pszBuf      The output buffer.
     * @param   cbBuf       The size of the output buffer.
     * @param   pszFormat   The format string.  This may use all IPRT extensions as
     *                      well as the debugger ones.
     * @param   ...         Arguments specified in the format string.
     */
    DECLCALLBACKMEMBER(size_t, pfnStrPrintf,(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
                                             const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(4, 5);

    /**
     * Command helper for formatting a string with debugger format specifiers.
     *
     * @returns The number of bytes written.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pszBuf      The output buffer.
     * @param   cbBuf       The size of the output buffer.
     * @param   pszFormat   The format string.  This may use all IPRT extensions as
     *                      well as the debugger ones.
     * @param   va          Arguments specified in the format string.
     */
    DECLCALLBACKMEMBER(size_t, pfnStrPrintfV,(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
                                              const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(4, 0);

    /**
     * Command helper for formatting and error message for a VBox status code.
     *
     * @returns VBox status code appropriate to return from a command.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   rc          The VBox status code.
     * @param   pszFormat   Format string for additional messages. Can be NULL.
     * @param   ...         Format arguments, optional.
     */
    DECLCALLBACKMEMBER(int, pfnVBoxError,(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(3, 4);

    /**
     * Command helper for formatting and error message for a VBox status code.
     *
     * @returns VBox status code appropriate to return from a command.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   rc          The VBox status code.
     * @param   pszFormat   Format string for additional messages. Can be NULL.
     * @param   args        Format arguments, optional.
     */
    DECLCALLBACKMEMBER(int, pfnVBoxErrorV,(PDBGCCMDHLP pCmdHlp, int rc,
                                           const char *pszFormat, va_list args)) RT_IPRT_FORMAT_ATTR(3, 0);

    /**
     * Command helper for reading memory specified by a DBGC variable.
     *
     * @returns VBox status code appropriate to return from a command.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pvBuffer    Where to store the read data.
     * @param   cbRead      Number of bytes to read.
     * @param   pVarPointer DBGC variable specifying where to start reading.
     * @param   pcbRead     Where to store the number of bytes actually read.
     *                      This optional, but it's useful when read GC virtual memory where a
     *                      page in the requested range might not be present.
     *                      If not specified not-present failure or end of a HC physical page
     *                      will cause failure.
     */
    DECLCALLBACKMEMBER(int, pfnMemRead,(PDBGCCMDHLP pCmdHlp, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead));

    /**
     * Command helper for writing memory specified by a DBGC variable.
     *
     * @returns VBox status code appropriate to return from a command.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pvBuffer    What to write.
     * @param   cbWrite     Number of bytes to write.
     * @param   pVarPointer DBGC variable specifying where to start reading.
     * @param   pcbWritten  Where to store the number of bytes written.
     *                      This is optional. If NULL be aware that some of the buffer
     *                      might have been written to the specified address.
     */
    DECLCALLBACKMEMBER(int, pfnMemWrite,(PDBGCCMDHLP pCmdHlp, const void *pvBuffer, size_t cbWrite, PCDBGCVAR pVarPointer, size_t *pcbWritten));

    /**
     * Executes command an expression.
     * (Hopefully the parser and functions are fully reentrant.)
     *
     * @returns VBox status code appropriate to return from a command.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pszExpr     The expression. Format string with the format DBGC extensions.
     * @param   ...         Format arguments.
     */
    DECLCALLBACKMEMBER(int, pfnExec,(PDBGCCMDHLP pCmdHlp, const char *pszExpr, ...)) RT_IPRT_FORMAT_ATTR(2, 3);

    /**
     * Evaluates an expression.
     * (Hopefully the parser and functions are fully reentrant.)
     *
     * @returns VBox status code appropriate to return from a command.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pResult     Where to store the result.
     * @param   pszExpr     The expression. Format string with the format DBGC extensions.
     * @param   va          Format arguments.
     */
    DECLCALLBACKMEMBER(int, pfnEvalV,(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult,
                                      const char *pszExpr, va_list va)) RT_IPRT_FORMAT_ATTR(3, 0);

    /**
     * Print an error and fail the current command.
     *
     * @returns VBox status code to pass upwards.
     *
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pCmd        The failing command.
     * @param   pszFormat   The error message format string.
     * @param   va          Format arguments.
     */
    DECLCALLBACKMEMBER(int, pfnFailV,(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd,
                                      const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(3, 0);

    /**
     * Print an error and fail the current command.
     *
     * @returns VBox status code to pass upwards.
     *
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pCmd        The failing command.
     * @param   rc          The status code indicating the failure.  This will
     *                      be appended to the message after a colon (': ').
     * @param   pszFormat   The error message format string.
     * @param   va          Format arguments.
     *
     * @see     DBGCCmdHlpFailRc
     */
    DECLCALLBACKMEMBER(int, pfnFailRcV,(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int rc,
                                        const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(4, 0);

    /**
     * Parser error.
     *
     * @returns VBox status code to pass upwards.
     *
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pCmd        The failing command, can be NULL but shouldn't.
     * @param   iArg        The offending argument, -1 when lazy.
     * @param   pszExpr     The expression.
     * @param   iLine       The line number.
     */
    DECLCALLBACKMEMBER(int, pfnParserError,(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int iArg, const char *pszExpr, unsigned iLine));

    /**
     * Converts a DBGC variable to a DBGF address structure.
     *
     * @returns VBox status code.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pVar        The variable to convert.
     * @param   pAddress    The target address.
     */
    DECLCALLBACKMEMBER(int, pfnVarToDbgfAddr,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress));

    /**
     * Converts a DBGF address structure to a DBGC variable.
     *
     * @returns VBox status code.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pAddress    The source address.
     * @param   pResult     The result variable.
     */
    DECLCALLBACKMEMBER(int, pfnVarFromDbgfAddr,(PDBGCCMDHLP pCmdHlp, PCDBGFADDRESS pAddress, PDBGCVAR pResult));

    /**
     * Converts a DBGC variable to a 64-bit number.
     *
     * @returns VBox status code.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pVar        The variable to convert.
     * @param   pu64Number  Where to store the number.
     */
    DECLCALLBACKMEMBER(int, pfnVarToNumber,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t *pu64Number));

    /**
     * Converts a DBGC variable to a boolean.
     *
     * @returns VBox status code.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pVar        The variable to convert.
     * @param   pf          Where to store the boolean.
     */
    DECLCALLBACKMEMBER(int, pfnVarToBool,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf));

    /**
     * Get the range of a variable in bytes, resolving symbols if necessary.
     *
     * @returns VBox status code.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pVar        The variable to convert.
     * @param   cbElement   Conversion factor for element ranges.
     * @param   cbDefault   The default range.
     * @param   pcbRange    The length of the range.
     */
    DECLCALLBACKMEMBER(int, pfnVarGetRange,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t cbElement, uint64_t cbDefault,
                                            uint64_t *pcbRange));

    /**
     * Converts a variable to one with the specified type.
     *
     * This preserves the range.
     *
     * @returns VBox status code.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   pVar        The variable to convert.
     * @param   enmToType   The target type.
     * @param   fConvSyms   If @c true, then attempt to resolve symbols.
     * @param   pResult     The output variable. Can be the same as @a pVar.
     */
    DECLCALLBACKMEMBER(int, pfnVarConvert,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, DBGCVARTYPE enmToType, bool fConvSyms,
                                           PDBGCVAR pResult));

    /**
     * Gets a DBGF output helper that directs the output to the debugger
     * console.
     *
     * @returns Pointer to the helper structure.
     * @param   pCmdHlp     Pointer to the command callback structure.
     */
    DECLCALLBACKMEMBER(PCDBGFINFOHLP, pfnGetDbgfOutputHlp,(PDBGCCMDHLP pCmdHlp));

    /**
     * Gets the ID currently selected CPU.
     *
     * @returns Current CPU ID.
     * @param   pCmdHlp     Pointer to the command callback structure.
     */
    DECLCALLBACKMEMBER(VMCPUID, pfnGetCurrentCpu,(PDBGCCMDHLP pCmdHlp));

    /**
     * Gets the mode the currently selected CPU is running in, in the current
     * context.
     *
     * @returns Current CPU mode.
     * @param   pCmdHlp     Pointer to the command callback structure.
     */
    DECLCALLBACKMEMBER(CPUMMODE, pfnGetCpuMode,(PDBGCCMDHLP pCmdHlp));

    /**
     * Prints the register set of the given CPU.
     *
     * @returns VBox status code.
     * @param   pCmdHlp     Pointer to the command callback structure.
     * @param   idCpu       The CPU ID to print the register set of.
     * @param   f64BitMode  True to dump 64-bit state, false to dump 32-bit state,
     *                      -1 to use the current CPU mode.
     * @param   fTerse      Flag to indicate whether to dump the complete register set.
     */
    DECLCALLBACKMEMBER(int, pfnRegPrintf, (PDBGCCMDHLP pCmdHlp, VMCPUID idCpu, int f64BitMode, bool fTerse));

    /** End marker (DBGCCMDHLP_MAGIC). */
    uint32_t                u32EndMarker;
} DBGCCMDHLP;

/** Magic value for DBGCCMDHLP::u32Magic. (Fyodor Mikhaylovich Dostoyevsky) */
#define DBGCCMDHLP_MAGIC    UINT32_C(18211111)


#if defined(IN_RING3) || defined(IN_SLICKEDIT)

/**
 * Command helper for writing formatted text to the debug console.
 *
 * @returns VBox status.
 * @param   pCmdHlp     Pointer to the command callback structure.
 * @param   pszFormat   The format string.  This may use all IPRT extensions as
 *                      well as the debugger ones.
 * @param   ...         Arguments specified in the format string.
 */
DECLINLINE(int) RT_IPRT_FORMAT_ATTR(2, 3) DBGCCmdHlpPrintf(PDBGCCMDHLP pCmdHlp, const char *pszFormat, ...)
{
    va_list va;
    int     rc;

    va_start(va, pszFormat);
    rc = pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, va);
    va_end(va);

    return rc;
}

/**
 * Command helper for writing formatted text to the debug console.
 *
 * @returns VBox status.
 * @param   pCmdHlp     Pointer to the command callback structure.
 * @param   pcbWritten  Where to store the amount of written characters on success.
 * @param   pszFormat   The format string.  This may use all IPRT extensions as
 *                      well as the debugger ones.
 * @param   ...         Arguments specified in the format string.
 */
DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpPrintfEx(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten,
                                                             const char *pszFormat, ...)
{
    va_list va;
    int     rc;

    va_start(va, pszFormat);
    rc = pCmdHlp->pfnPrintfV(pCmdHlp, pcbWritten, pszFormat, va);
    va_end(va);

    return rc;
}

/**
 * Command helper for writing formatted text to the debug console.
 *
 * @returns Number of bytes written.
 * @param   pCmdHlp     Pointer to the command callback structure.
 * @param   pszFormat   The format string.  This may use all IPRT extensions as
 *                      well as the debugger ones.
 * @param   ...         Arguments specified in the format string.
 */
DECLINLINE(size_t) RT_IPRT_FORMAT_ATTR(2, 3) DBGCCmdHlpPrintfLen(PDBGCCMDHLP pCmdHlp, const char *pszFormat, ...)
{
    va_list va;
    int     rc;
    size_t  cbWritten = 0;

    va_start(va, pszFormat);
    rc = pCmdHlp->pfnPrintfV(pCmdHlp, &cbWritten, pszFormat, va);
    va_end(va);

    return RT_SUCCESS(rc) ? cbWritten : 0;
}

/**
 * @copydoc DBGCCMDHLP::pfnStrPrintf
 */
DECLINLINE(size_t) RT_IPRT_FORMAT_ATTR(4, 5) DBGCCmdHlpStrPrintf(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
                                                                 const char *pszFormat, ...)
{
    va_list va;
    size_t  cch;

    va_start(va, pszFormat);
    cch = pCmdHlp->pfnStrPrintfV(pCmdHlp, pszBuf, cbBuf, pszFormat, va);
    va_end(va);

    return cch;
}

/**
 * @copydoc DBGCCMDHLP::pfnVBoxError
 */
DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpVBoxError(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)
{
    va_list va;

    va_start(va, pszFormat);
    rc = pCmdHlp->pfnVBoxErrorV(pCmdHlp, rc, pszFormat, va);
    va_end(va);

    return rc;
}

/**
 * @copydoc DBGCCMDHLP::pfnMemRead
 */
DECLINLINE(int) DBGCCmdHlpMemRead(PDBGCCMDHLP pCmdHlp, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead)
{
    return pCmdHlp->pfnMemRead(pCmdHlp, pvBuffer, cbRead, pVarPointer, pcbRead);
}

/**
 * Evaluates an expression.
 * (Hopefully the parser and functions are fully reentrant.)
 *
 * @returns VBox status code appropriate to return from a command.
 * @param   pCmdHlp     Pointer to the command callback structure.
 * @param   pResult     Where to store the result.
 * @param   pszExpr     The expression. Format string with the format DBGC extensions.
 * @param   ...         Format arguments.
 */
DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpEval(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult, const char *pszExpr, ...)
{
    va_list va;
    int     rc;

    va_start(va, pszExpr);
    rc = pCmdHlp->pfnEvalV(pCmdHlp, pResult, pszExpr, va);
    va_end(va);

    return rc;
}

/**
 * Print an error and fail the current command.
 *
 * @returns VBox status code to pass upwards.
 *
 * @param   pCmdHlp     Pointer to the command callback structure.
 * @param   pCmd        The failing command.
 * @param   pszFormat   The error message format string.
 * @param   ...         Format arguments.
 */
DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpFail(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, const char *pszFormat, ...)
{
    va_list va;
    int     rc;

    va_start(va, pszFormat);
    rc = pCmdHlp->pfnFailV(pCmdHlp, pCmd, pszFormat, va);
    va_end(va);

    return rc;
}

/**
 * Print an error and fail the current command.
 *
 * Usage example:
 * @code
    int rc = VMMR3Something(pVM);
    if (RT_FAILURE(rc))
        return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "VMMR3Something");
    return VINF_SUCCESS;
 * @endcode
 *
 * @returns VBox status code to pass upwards.
 *
 * @param   pCmdHlp     Pointer to the command callback structure.
 * @param   pCmd        The failing command.
 * @param   rc          The status code indicating the failure.
 * @param   pszFormat   The error message format string.
 * @param   ...         Format arguments.
 */
DECLINLINE(int) RT_IPRT_FORMAT_ATTR(4, 5) DBGCCmdHlpFailRc(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int rc,
                                                           const char *pszFormat, ...)
{
    va_list va;

    va_start(va, pszFormat);
    rc = pCmdHlp->pfnFailRcV(pCmdHlp, pCmd, rc, pszFormat, va);
    va_end(va);

    return rc;
}

/**
 * @copydoc DBGCCMDHLP::pfnParserError
 */
DECLINLINE(int) DBGCCmdHlpParserError(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int iArg, const char *pszExpr, unsigned iLine)
{
    return pCmdHlp->pfnParserError(pCmdHlp, pCmd, iArg, pszExpr, iLine);
}

/** Assert+return like macro for checking parser sanity.
 * Returns with failure if the precodition is not met. */
#define DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, iArg, expr) \
    do { \
        if (!(expr)) \
            return DBGCCmdHlpParserError(pCmdHlp, pCmd, iArg, #expr, __LINE__); \
    } while (0)

/** Assert+return like macro that the VM handle is present.
 * Returns with failure if the VM handle is NIL.  */
#define DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM) \
    do { \
        if (!(pUVM)) \
            return DBGCCmdHlpFail(pCmdHlp, pCmd, "No VM selected"); \
    } while (0)

/**
 * @copydoc DBGCCMDHLP::pfnVarToDbgfAddr
 */
DECLINLINE(int) DBGCCmdHlpVarToDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
{
    return pCmdHlp->pfnVarToDbgfAddr(pCmdHlp, pVar, pAddress);
}

/**
 * @copydoc DBGCCMDHLP::pfnVarFromDbgfAddr
 */
DECLINLINE(int) DBGCCmdHlpVarFromDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGFADDRESS pAddress, PDBGCVAR pResult)
{
    return pCmdHlp->pfnVarFromDbgfAddr(pCmdHlp, pAddress, pResult);
}

/**
 * Converts an variable to a flat address.
 *
 * @returns VBox status code.
 * @param   pCmdHlp     Pointer to the command callback structure.
 * @param   pVar        The variable to convert.
 * @param   pFlatPtr    Where to store the flat address.
 */
DECLINLINE(int) DBGCCmdHlpVarToFlatAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PRTGCPTR pFlatPtr)
{
    DBGFADDRESS Addr;
    int rc = pCmdHlp->pfnVarToDbgfAddr(pCmdHlp, pVar, &Addr);
    if (RT_SUCCESS(rc))
        *pFlatPtr = Addr.FlatPtr;
    return rc;
}

/**
 * @copydoc DBGCCMDHLP::pfnVarToNumber
 */
DECLINLINE(int) DBGCCmdHlpVarToNumber(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t *pu64Number)
{
    return pCmdHlp->pfnVarToNumber(pCmdHlp, pVar, pu64Number);
}

/**
 * @copydoc DBGCCMDHLP::pfnVarToBool
 */
DECLINLINE(int) DBGCCmdHlpVarToBool(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf)
{
    return pCmdHlp->pfnVarToBool(pCmdHlp, pVar, pf);
}

/**
 * @copydoc DBGCCMDHLP::pfnVarGetRange
 */
DECLINLINE(int) DBGCCmdHlpVarGetRange(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t cbElement, uint64_t cbDefault, uint64_t *pcbRange)
{
    return pCmdHlp->pfnVarGetRange(pCmdHlp, pVar, cbElement, cbDefault, pcbRange);
}

/**
 * @copydoc DBGCCMDHLP::pfnVarConvert
 */
DECLINLINE(int) DBGCCmdHlpConvert(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, DBGCVARTYPE enmToType, bool fConvSyms, PDBGCVAR pResult)
{
    return pCmdHlp->pfnVarConvert(pCmdHlp, pVar, enmToType, fConvSyms, pResult);
}

/**
 * @copydoc DBGCCMDHLP::pfnGetDbgfOutputHlp
 */
DECLINLINE(PCDBGFINFOHLP) DBGCCmdHlpGetDbgfOutputHlp(PDBGCCMDHLP pCmdHlp)
{
    return pCmdHlp->pfnGetDbgfOutputHlp(pCmdHlp);
}

/**
 * @copydoc DBGCCMDHLP::pfnGetCurrentCpu
 */
DECLINLINE(VMCPUID) DBGCCmdHlpGetCurrentCpu(PDBGCCMDHLP pCmdHlp)
{
    return pCmdHlp->pfnGetCurrentCpu(pCmdHlp);
}

/**
 * @copydoc DBGCCMDHLP::pfnGetCpuMode
 */
DECLINLINE(CPUMMODE) DBGCCmdHlpGetCpuMode(PDBGCCMDHLP pCmdHlp)
{
    return pCmdHlp->pfnGetCpuMode(pCmdHlp);
}

/**
 * @copydoc DBGCCMDHLP::pfnRegPrintf
 */
DECLINLINE(int) DBGCCmdHlpRegPrintf(PDBGCCMDHLP pCmdHlp, VMCPUID idCpu, int f64BitMode, bool fTerse)
{
    return pCmdHlp->pfnRegPrintf(pCmdHlp, idCpu, f64BitMode, fTerse);
}

#endif /* IN_RING3 */



/**
 * Command handler.
 *
 * The console will call the handler for a command once it's finished
 * parsing the user input.  The command handler function is responsible
 * for executing the command itself.
 *
 * @returns VBox status.
 * @param   pCmd        Pointer to the command descriptor (as registered).
 * @param   pCmdHlp     Pointer to command helper functions.
 * @param   pUVM        The user mode VM handle, can in theory be NULL.
 * @param   paArgs      Pointer to (readonly) array of arguments.
 * @param   cArgs       Number of arguments in the array.
 */
typedef DECLCALLBACKTYPE(int, FNDBGCCMD,(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs));
/** Pointer to a FNDBGCCMD() function. */
typedef FNDBGCCMD *PFNDBGCCMD;

/**
 * DBGC command descriptor.
 */
typedef struct DBGCCMD
{
    /** Command string. */
    const char     *pszCmd;
    /** Minimum number of arguments. */
    unsigned        cArgsMin;
    /** Max number of arguments. */
    unsigned        cArgsMax;
    /** Argument descriptors (array). */
    PCDBGCVARDESC   paArgDescs;
    /** Number of argument descriptors. */
    unsigned        cArgDescs;
    /** flags. (reserved for now) */
    unsigned        fFlags;
    /** Handler function. */
    PFNDBGCCMD      pfnHandler;
    /** Command syntax. */
    const char     *pszSyntax;
    /** Command description. */
    const char     *pszDescription;
} DBGCCMD;

/** DBGCCMD Flags.
 * @{
 */
/** @} */


/**
 * Function handler.
 *
 * The console will call the handler for a command once it's finished
 * parsing the user input.  The command handler function is responsible
 * for executing the command itself.
 *
 * @returns VBox status.
 * @param   pFunc       Pointer to the function descriptor (as registered).
 * @param   pCmdHlp     Pointer to command helper functions.
 * @param   pUVM        The user mode VM handle, can in theory be NULL.
 * @param   paArgs      Pointer to (readonly) array of arguments.
 * @param   cArgs       Number of arguments in the array.
 * @param   pResult     Where to return the result.
 */
typedef DECLCALLBACKTYPE(int, FNDBGCFUNC,(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs,
                                          PDBGCVAR pResult));
/** Pointer to a FNDBGCFUNC() function. */
typedef FNDBGCFUNC *PFNDBGCFUNC;

/**
 * DBGC function descriptor.
 */
typedef struct DBGCFUNC
{
    /** Command string. */
    const char     *pszFuncNm;
    /** Minimum number of arguments. */
    unsigned        cArgsMin;
    /** Max number of arguments. */
    unsigned        cArgsMax;
    /** Argument descriptors (array). */
    PCDBGCVARDESC   paArgDescs;
    /** Number of argument descriptors. */
    unsigned        cArgDescs;
    /** flags. (reserved for now) */
    unsigned        fFlags;
    /** Handler function. */
    PFNDBGCFUNC     pfnHandler;
    /** Function syntax. */
    const char     *pszSyntax;
    /** Function description. */
    const char     *pszDescription;
} DBGCFUNC;


/** Pointer to a const I/O callback table. */
typedef const struct DBGCIO *PCDBGCIO;

/**
 * I/O callback table.
 */
typedef struct DBGCIO
{
    /**
     * Destroys the given I/O instance.
     *
     * @returns nothing.
     * @param   pIo         Pointer to the I/O structure supplied by the I/O provider.
     */
    DECLCALLBACKMEMBER(void, pfnDestroy, (PCDBGCIO pIo));

    /**
     * Wait for input available for reading.
     *
     * @returns Flag whether there is input ready upon return.
     * @retval  true if there is input ready.
     * @retval  false if there not input ready.
     * @param   pIo         Pointer to the I/O structure supplied by
     *                      the I/O provider. The backend can use this to find it's instance data.
     * @param   cMillies    Number of milliseconds to wait on input data.
     */
    DECLCALLBACKMEMBER(bool, pfnInput, (PCDBGCIO pIo, uint32_t cMillies));

    /**
     * Read input.
     *
     * @returns VBox status code.
     * @param   pIo         Pointer to the I/O structure supplied by
     *                      the I/O provider. The backend can use this to find it's instance data.
     * @param   pvBuf       Where to put the bytes we read.
     * @param   cbBuf       Maximum nymber of bytes to read.
     * @param   pcbRead     Where to store the number of bytes actually read.
     *                      If NULL the entire buffer must be filled for a
     *                      successful return.
     */
    DECLCALLBACKMEMBER(int, pfnRead, (PCDBGCIO pIo, void *pvBuf, size_t cbBuf, size_t *pcbRead));

    /**
     * Write (output).
     *
     * @returns VBox status code.
     * @param   pIo         Pointer to the I/O structure supplied by
     *                      the I/O provider. The backend can use this to find it's instance data.
     * @param   pvBuf       What to write.
     * @param   cbBuf       Number of bytes to write.
     * @param   pcbWritten  Where to store the number of bytes actually written.
     *                      If NULL the entire buffer must be successfully written.
     */
    DECLCALLBACKMEMBER(int, pfnWrite, (PCDBGCIO pIo, const void *pvBuf, size_t cbBuf, size_t *pcbWritten));

    /**
     * Marks the beginning of a new packet being sent - optional.
     *
     * @returns VBox status code.
     * @param   pIo         Pointer to the I/O structure supplied by
     *                      the I/O provider. The backend can use this to find it's instance data.
     * @param   cbPktHint   Size of the packet in bytes, serves as a hint for the I/O provider to arrange buffers.
     *                      Give 0 if size is unknown upfront.
     */
    DECLCALLBACKMEMBER(int, pfnPktBegin, (PCDBGCIO pIo, size_t cbPktHint));

    /**
     * Marks the end of the packet - optional.
     *
     * @returns VBox status code.
     * @param   pIo         Pointer to the I/O structure supplied by
     *                      the I/O provider. The backend can use this to find it's instance data.
     *
     * @note Some I/O providers might decide to send data only when this is called not in the
     *       DBGCIO::pfnWrite callback.
     */
    DECLCALLBACKMEMBER(int, pfnPktEnd, (PCDBGCIO pIo));

    /**
     * Ready / busy notification.
     *
     * @returns nothing.
     * @param   pIo         Pointer to the I/O structure supplied by
     *                      the I/O provider. The backend can use this to find it's instance data.
     * @param   fReady      Whether it's ready (true) or busy (false).
     */
    DECLCALLBACKMEMBER(void, pfnSetReady, (PCDBGCIO pIo, bool fReady));

} DBGCIO;
/** Pointer to an I/O callback table. */
typedef DBGCIO *PDBGCIO;


DBGDECL(int)    DBGCCreate(PUVM pUVM, PCDBGCIO pIo, unsigned fFlags);
DBGDECL(int)    DBGCRegisterCommands(PCDBGCCMD paCommands, unsigned cCommands);
DBGDECL(int)    DBGCDeregisterCommands(PCDBGCCMD paCommands, unsigned cCommands);

DBGDECL(int)    DBGCIoCreate(PUVM pUVM, void **ppvData);
DBGDECL(int)    DBGCIoTerminate(PUVM pUVM, void *pvData);

/** @} */

#endif /* IN_RING3 */

/** @} */
RT_C_DECLS_END

#endif /* !VBOX_INCLUDED_dbg_h */