VirtualBox

source: vbox/trunk/src/VBox/Debugger/testcase/tstDBGCParser.cpp@ 86327

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

Debugger: Allow for different I/O providers instead of only TCP

So far TCP was the only option to communicate remotely with the internal debugger, the other option
was to use the console from the GUI directly. This commit reworks basic I/O to allow for different
providers where TCP is just one option. The second one being introduced is an IPC provider using a local
socket or named pipe depending on the platform. This allows for Windows kernel debugging over a pipe
using the KD stub in VirtualBox and WinDbg running on the host (not tested yet).

Furthermore this commit allows multiple stubs to be listening for connections at the same time, so
one can have a GDB stub listening on one TCP port and the native VBox debugger listening on another one
or even using a different I/O provider. Only one session can be active at a time though, because sharing
debugger states is impossible. To configure this the following CFGM keys need to be set for each listener:

"DBGC/<Some unique ID>/Provider" "tcp|ipc"
"DBGC/<Some unique ID>/StubType" "native|gdb|kd"
"DBGC/<Some unique ID>/Address" "<ip>|<local named pipe or socket path>"
"DBGC/<Some unique ID>/Port" "<port>" (for TCP only)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 37.8 KB
Line 
1/* $Id: tstDBGCParser.cpp 86327 2020-09-28 16:20:50Z vboxsync $ */
2/** @file
3 * DBGC Testcase - Command Parser.
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.215389.xyz. 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
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <VBox/dbg.h>
23#include "../DBGCInternal.h"
24
25#include <iprt/string.h>
26#include <iprt/test.h>
27#include <VBox/err.h>
28
29
30/*********************************************************************************************************************************
31* Internal Functions *
32*********************************************************************************************************************************/
33static DECLCALLBACK(bool) tstDBGCBackInput(PCDBGCIO pBack, uint32_t cMillies);
34static DECLCALLBACK(int) tstDBGCBackRead(PCDBGCIO pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead);
35static DECLCALLBACK(int) tstDBGCBackWrite(PCDBGCIO pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten);
36static DECLCALLBACK(void) tstDBGCBackSetReady(PCDBGCIO pBack, bool fReady);
37
38
39/*********************************************************************************************************************************
40* Global Variables *
41*********************************************************************************************************************************/
42/** The test handle. */
43static RTTEST g_hTest = NIL_RTTEST;
44
45/** The DBGC I/O structure for use in this testcase. */
46static DBGCIO g_tstBack =
47{
48 NULL, /**pfnDestroy*/
49 tstDBGCBackInput,
50 tstDBGCBackRead,
51 tstDBGCBackWrite,
52 tstDBGCBackSetReady
53};
54/** For keeping track of output prefixing. */
55static bool g_fPendingPrefix = true;
56/** Pointer to the current input position. */
57const char *g_pszInput = NULL;
58/** The output of the last command. */
59static char g_szOutput[1024];
60/** The current offset into g_szOutput. */
61static size_t g_offOutput = 0;
62
63
64/**
65 * Checks if there is input.
66 *
67 * @returns true if there is input ready.
68 * @returns false if there not input ready.
69 * @param pBack Pointer to the backend structure supplied by
70 * the backend. The backend can use this to find
71 * it's instance data.
72 * @param cMillies Number of milliseconds to wait on input data.
73 */
74static DECLCALLBACK(bool) tstDBGCBackInput(PCDBGCIO pBack, uint32_t cMillies)
75{
76 return g_pszInput != NULL
77 && *g_pszInput != '\0';
78}
79
80
81/**
82 * Read input.
83 *
84 * @returns VBox status code.
85 * @param pBack Pointer to the backend structure supplied by
86 * the backend. The backend can use this to find
87 * it's instance data.
88 * @param pvBuf Where to put the bytes we read.
89 * @param cbBuf Maximum nymber of bytes to read.
90 * @param pcbRead Where to store the number of bytes actually read.
91 * If NULL the entire buffer must be filled for a
92 * successful return.
93 */
94static DECLCALLBACK(int) tstDBGCBackRead(PCDBGCIO pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead)
95{
96 if (g_pszInput && *g_pszInput)
97 {
98 size_t cb = strlen(g_pszInput);
99 if (cb > cbBuf)
100 cb = cbBuf;
101 *pcbRead = cb;
102 memcpy(pvBuf, g_pszInput, cb);
103 g_pszInput += cb;
104 }
105 else
106 *pcbRead = 0;
107 return VINF_SUCCESS;
108}
109
110
111/**
112 * Write (output).
113 *
114 * @returns VBox status code.
115 * @param pBack Pointer to the backend structure supplied by
116 * the backend. The backend can use this to find
117 * it's instance data.
118 * @param pvBuf What to write.
119 * @param cbBuf Number of bytes to write.
120 * @param pcbWritten Where to store the number of bytes actually written.
121 * If NULL the entire buffer must be successfully written.
122 */
123static DECLCALLBACK(int) tstDBGCBackWrite(PCDBGCIO pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
124{
125 const char *pch = (const char *)pvBuf;
126 if (pcbWritten)
127 *pcbWritten = cbBuf;
128 while (cbBuf-- > 0)
129 {
130 /* screen/log output */
131 if (g_fPendingPrefix)
132 {
133 RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "OUTPUT: ");
134 g_fPendingPrefix = false;
135 }
136 if (*pch == '\n')
137 g_fPendingPrefix = true;
138 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "%c", *pch);
139
140 /* buffer output */
141 if (g_offOutput < sizeof(g_szOutput) - 1)
142 {
143 g_szOutput[g_offOutput++] = *pch;
144 g_szOutput[g_offOutput] = '\0';
145 }
146
147 /* advance */
148 pch++;
149 }
150 return VINF_SUCCESS;
151}
152
153
154/**
155 * Ready / busy notification.
156 *
157 * @param pBack Pointer to the backend structure supplied by
158 * the backend. The backend can use this to find
159 * it's instance data.
160 * @param fReady Whether it's ready (true) or busy (false).
161 */
162static DECLCALLBACK(void) tstDBGCBackSetReady(PCDBGCIO pBack, bool fReady)
163{
164}
165
166
167/**
168 * Completes the output, making sure that we're in
169 * the 1 position of a new line.
170 */
171static void tstCompleteOutput(void)
172{
173 if (!g_fPendingPrefix)
174 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "\n");
175 g_fPendingPrefix = true;
176}
177
178
179/**
180 * Checks if two DBGC variables are identical
181 *
182 * @returns
183 * @param pVar1 .
184 * @param pVar2 .
185 */
186bool DBGCVarAreIdentical(PCDBGCVAR pVar1, PCDBGCVAR pVar2)
187{
188 if (!pVar1)
189 return false;
190 if (pVar1 == pVar2)
191 return true;
192
193 if (pVar1->enmType != pVar2->enmType)
194 return false;
195 switch (pVar1->enmType)
196 {
197 case DBGCVAR_TYPE_GC_FLAT:
198 if (pVar1->u.GCFlat != pVar2->u.GCFlat)
199 return false;
200 break;
201 case DBGCVAR_TYPE_GC_FAR:
202 if (pVar1->u.GCFar.off != pVar2->u.GCFar.off)
203 return false;
204 if (pVar1->u.GCFar.sel != pVar2->u.GCFar.sel)
205 return false;
206 break;
207 case DBGCVAR_TYPE_GC_PHYS:
208 if (pVar1->u.GCPhys != pVar2->u.GCPhys)
209 return false;
210 break;
211 case DBGCVAR_TYPE_HC_FLAT:
212 if (pVar1->u.pvHCFlat != pVar2->u.pvHCFlat)
213 return false;
214 break;
215 case DBGCVAR_TYPE_HC_PHYS:
216 if (pVar1->u.HCPhys != pVar2->u.HCPhys)
217 return false;
218 break;
219 case DBGCVAR_TYPE_NUMBER:
220 if (pVar1->u.u64Number != pVar2->u.u64Number)
221 return false;
222 break;
223 case DBGCVAR_TYPE_STRING:
224 case DBGCVAR_TYPE_SYMBOL:
225 if (RTStrCmp(pVar1->u.pszString, pVar2->u.pszString) != 0)
226 return false;
227 break;
228 default:
229 AssertFailedReturn(false);
230 }
231
232 if (pVar1->enmRangeType != pVar2->enmRangeType)
233 return false;
234 switch (pVar1->enmRangeType)
235 {
236 case DBGCVAR_RANGE_NONE:
237 break;
238
239 case DBGCVAR_RANGE_ELEMENTS:
240 case DBGCVAR_RANGE_BYTES:
241 if (pVar1->u64Range != pVar2->u64Range)
242 return false;
243 break;
244 default:
245 AssertFailedReturn(false);
246 }
247
248 return true;
249}
250
251/**
252 * Tries one command string.
253 * @param pDbgc Pointer to the debugger instance.
254 * @param pszCmds The command to test.
255 * @param rcCmd The expected result.
256 * @param fNoExecute When set, the command is not executed.
257 * @param pszExpected Expected output. This does not need to include all
258 * of the output, just the start of it. Thus the
259 * prompt can be omitted.
260 * @param cArgs The number of expected arguments. -1 if we don't
261 * want to check the parsed arguments.
262 * @param va Info about expected parsed arguments. For each
263 * argument a DBGCVARTYPE, value (depends on type),
264 * DBGCVARRANGETYPE and optionally range value.
265 */
266static void tstTryExV(PDBGC pDbgc, const char *pszCmds, int rcCmd, bool fNoExecute, const char *pszExpected,
267 int32_t cArgs, va_list va)
268{
269 RT_ZERO(g_szOutput);
270 g_offOutput = 0;
271 g_pszInput = pszCmds;
272 if (strchr(pszCmds, '\0')[-1] == '\n')
273 RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s", pszCmds);
274 else
275 RTTestPrintfNl(g_hTest, RTTESTLVL_ALWAYS, "RUNNING: %s\n", pszCmds);
276
277 pDbgc->rcCmd = VERR_INTERNAL_ERROR;
278 dbgcProcessInput(pDbgc, fNoExecute);
279 tstCompleteOutput();
280
281 if (pDbgc->rcCmd != rcCmd)
282 RTTestFailed(g_hTest, "rcCmd=%Rrc expected =%Rrc\n", pDbgc->rcCmd, rcCmd);
283 else if ( !fNoExecute
284 && pszExpected
285 && strncmp(pszExpected, g_szOutput, strlen(pszExpected)))
286 RTTestFailed(g_hTest, "Wrong output - expected \"%s\"", pszExpected);
287
288 if (cArgs >= 0)
289 {
290 PCDBGCVAR paArgs = pDbgc->aArgs;
291 for (int32_t iArg = 0; iArg < cArgs; iArg++)
292 {
293 DBGCVAR ExpectedArg;
294 ExpectedArg.enmType = (DBGCVARTYPE)va_arg(va, int/*DBGCVARTYPE*/);
295 switch (ExpectedArg.enmType)
296 {
297 case DBGCVAR_TYPE_GC_FLAT: ExpectedArg.u.GCFlat = va_arg(va, RTGCPTR); break;
298 case DBGCVAR_TYPE_GC_FAR: ExpectedArg.u.GCFar.sel = va_arg(va, int /*RTSEL*/);
299 ExpectedArg.u.GCFar.off = va_arg(va, uint32_t); break;
300 case DBGCVAR_TYPE_GC_PHYS: ExpectedArg.u.GCPhys = va_arg(va, RTGCPHYS); break;
301 case DBGCVAR_TYPE_HC_FLAT: ExpectedArg.u.pvHCFlat = va_arg(va, void *); break;
302 case DBGCVAR_TYPE_HC_PHYS: ExpectedArg.u.HCPhys = va_arg(va, RTHCPHYS); break;
303 case DBGCVAR_TYPE_NUMBER: ExpectedArg.u.u64Number = va_arg(va, uint64_t); break;
304 case DBGCVAR_TYPE_STRING: ExpectedArg.u.pszString = va_arg(va, const char *); break;
305 case DBGCVAR_TYPE_SYMBOL: ExpectedArg.u.pszString = va_arg(va, const char *); break;
306 default:
307 RTTestFailed(g_hTest, "enmType=%u iArg=%u\n", ExpectedArg.enmType, iArg);
308 ExpectedArg.u.u64Number = 0;
309 break;
310 }
311 ExpectedArg.enmRangeType = (DBGCVARRANGETYPE)va_arg(va, int /*DBGCVARRANGETYPE*/);
312 switch (ExpectedArg.enmRangeType)
313 {
314 case DBGCVAR_RANGE_NONE: ExpectedArg.u64Range = 0; break;
315 case DBGCVAR_RANGE_ELEMENTS: ExpectedArg.u64Range = va_arg(va, uint64_t); break;
316 case DBGCVAR_RANGE_BYTES: ExpectedArg.u64Range = va_arg(va, uint64_t); break;
317 default:
318 RTTestFailed(g_hTest, "enmRangeType=%u iArg=%u\n", ExpectedArg.enmRangeType, iArg);
319 ExpectedArg.u64Range = 0;
320 break;
321 }
322
323 if (!DBGCVarAreIdentical(&ExpectedArg, &paArgs[iArg]))
324 RTTestFailed(g_hTest,
325 "Arg #%u\n"
326 "actual: enmType=%u u64=%#RX64 enmRangeType=%u u64Range=%#RX64\n"
327 "expected: enmType=%u u64=%#RX64 enmRangeType=%u u64Range=%#RX64\n",
328 iArg,
329 paArgs[iArg].enmType, paArgs[iArg].u.u64Number, paArgs[iArg].enmRangeType, paArgs[iArg].u64Range,
330 ExpectedArg.enmType, ExpectedArg.u.u64Number, ExpectedArg.enmRangeType, ExpectedArg.u64Range);
331 }
332 }
333}
334
335/**
336 * Tries one command string.
337 *
338 * @param pDbgc Pointer to the debugger instance.
339 * @param pszCmds The command to test.
340 * @param rcCmd The expected result.
341 * @param fNoExecute When set, the command is not executed.
342 * @param pszExpected Expected output. This does not need to include all
343 * of the output, just the start of it. Thus the
344 * prompt can be omitted.
345 * @param cArgs The number of expected arguments. -1 if we don't
346 * want to check the parsed arguments.
347 * @param ... Info about expected parsed arguments. For each
348 * argument a DBGCVARTYPE, value (depends on type),
349 * DBGCVARRANGETYPE and optionally range value.
350 */
351static void tstTryEx(PDBGC pDbgc, const char *pszCmds, int rcCmd, bool fNoExecute, const char *pszExpected, int32_t cArgs, ...)
352{
353 va_list va;
354 va_start(va, cArgs);
355 tstTryExV(pDbgc, pszCmds, rcCmd, fNoExecute, pszExpected, cArgs, va);
356 va_end(va);
357}
358
359
360/**
361 * Tries one command string without executing it.
362 *
363 * @param pDbgc Pointer to the debugger instance.
364 * @param pszCmds The command to test.
365 * @param rcCmd The expected result.
366 */
367static void tstTry(PDBGC pDbgc, const char *pszCmds, int rcCmd)
368{
369 return tstTryEx(pDbgc, pszCmds, rcCmd, true /*fNoExecute*/, NULL, -1);
370}
371
372
373#ifdef SOME_UNUSED_FUNCTION
374/**
375 * Tries to execute one command string.
376 * @param pDbgc Pointer to the debugger instance.
377 * @param pszCmds The command to test.
378 * @param rcCmd The expected result.
379 * @param pszExpected Expected output. This does not need to include all
380 * of the output, just the start of it. Thus the
381 * prompt can be omitted.
382 */
383static void tstTryExec(PDBGC pDbgc, const char *pszCmds, int rcCmd, const char *pszExpected)
384{
385 return tstTryEx(pDbgc, pszCmds, rcCmd, false /*fNoExecute*/, pszExpected, -1);
386}
387#endif
388
389
390/**
391 * Test an operator on an expression resulting a plain number.
392 *
393 * @param pDbgc Pointer to the debugger instance.
394 * @param pszExpr The express to test.
395 * @param u64Expect The expected result.
396 */
397static void tstNumOp(PDBGC pDbgc, const char *pszExpr, uint64_t u64Expect)
398{
399 char szCmd[80];
400 RTStrPrintf(szCmd, sizeof(szCmd), "format %s\n", pszExpr);
401
402 char szExpected[80];
403 RTStrPrintf(szExpected, sizeof(szExpected),
404 "Number: hex %llx dec 0i%lld oct 0t%llo", u64Expect, u64Expect, u64Expect);
405
406 return tstTryEx(pDbgc, szCmd, VINF_SUCCESS, false /*fNoExecute*/, szExpected, -1);
407}
408
409
410/*
411 *
412 * CodeView emulation commands.
413 * CodeView emulation commands.
414 * CodeView emulation commands.
415 *
416 */
417
418
419static void testCodeView_ba(PDBGC pDbgc)
420{
421 RTTestISub("codeview - ba");
422 tstTry(pDbgc, "ba x 1 0f000:0000\n", VINF_SUCCESS);
423 tstTry(pDbgc, "ba x 1 0f000:0000 0\n", VINF_SUCCESS);
424 tstTry(pDbgc, "ba x 1 0f000:0000 0 ~0\n", VINF_SUCCESS);
425 tstTry(pDbgc, "ba x 1 0f000:0000 0 ~0 \"command\"\n", VINF_SUCCESS);
426 tstTry(pDbgc, "ba x 1 0f000:0000 0 ~0 \"command\" too_many\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
427 tstTry(pDbgc, "ba x 1\n", VERR_DBGC_PARSE_TOO_FEW_ARGUMENTS);
428
429 tstTryEx(pDbgc, "ba x 1 0f000:1234 5 1000 \"command\"\n", VINF_SUCCESS,
430 true /*fNoExecute*/, NULL /*pszExpected*/, 6 /*cArgs*/,
431 DBGCVAR_TYPE_STRING, "x", DBGCVAR_RANGE_BYTES, UINT64_C(1),
432 DBGCVAR_TYPE_NUMBER, UINT64_C(1), DBGCVAR_RANGE_NONE,
433 DBGCVAR_TYPE_GC_FAR, 0xf000, UINT32_C(0x1234), DBGCVAR_RANGE_NONE,
434 DBGCVAR_TYPE_NUMBER, UINT64_C(0x5), DBGCVAR_RANGE_NONE,
435 DBGCVAR_TYPE_NUMBER, UINT64_C(0x1000), DBGCVAR_RANGE_NONE,
436 DBGCVAR_TYPE_STRING, "command", DBGCVAR_RANGE_BYTES, UINT64_C(7));
437
438 tstTryEx(pDbgc, "ba x 1 %0f000:1234 5 1000 \"command\"\n", VINF_SUCCESS,
439 true /*fNoExecute*/, NULL /*pszExpected*/, 6 /*cArgs*/,
440 DBGCVAR_TYPE_STRING, "x", DBGCVAR_RANGE_BYTES, UINT64_C(1),
441 DBGCVAR_TYPE_NUMBER, UINT64_C(1), DBGCVAR_RANGE_NONE,
442 DBGCVAR_TYPE_GC_FLAT, UINT64_C(0xf1234), DBGCVAR_RANGE_NONE,
443 DBGCVAR_TYPE_NUMBER, UINT64_C(0x5), DBGCVAR_RANGE_NONE,
444 DBGCVAR_TYPE_NUMBER, UINT64_C(0x1000), DBGCVAR_RANGE_NONE,
445 DBGCVAR_TYPE_STRING, "command", DBGCVAR_RANGE_BYTES, UINT64_C(7));
446
447 tstTry(pDbgc, "ba x 1 bad:bad 5 1000 \"command\"\n", VINF_SUCCESS);
448 tstTry(pDbgc, "ba x 1 %bad:bad 5 1000 \"command\"\n", VERR_DBGC_PARSE_CONVERSION_FAILED);
449
450 tstTryEx(pDbgc, "ba f 1 0f000:1234 5 1000 \"command\"\n", VINF_SUCCESS,
451 true /*fNoExecute*/, NULL /*pszExpected*/, 6 /*cArgs*/,
452 DBGCVAR_TYPE_STRING, "f", DBGCVAR_RANGE_BYTES, UINT64_C(1),
453 DBGCVAR_TYPE_NUMBER, UINT64_C(1), DBGCVAR_RANGE_NONE,
454 DBGCVAR_TYPE_GC_FAR, 0xf000, UINT32_C(0x1234), DBGCVAR_RANGE_NONE,
455 DBGCVAR_TYPE_NUMBER, UINT64_C(0x5), DBGCVAR_RANGE_NONE,
456 DBGCVAR_TYPE_NUMBER, UINT64_C(0x1000), DBGCVAR_RANGE_NONE,
457 DBGCVAR_TYPE_STRING, "command", DBGCVAR_RANGE_BYTES, UINT64_C(7));
458
459 tstTry(pDbgc, "ba x 1 0f000:1234 qnx 1000 \"command\"\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
460 tstTry(pDbgc, "ba x 1 0f000:1234 5 qnx \"command\"\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
461 tstTry(pDbgc, "ba x qnx 0f000:1234 5 1000 \"command\"\n", VERR_DBGC_PARSE_INVALID_NUMBER);
462 tstTry(pDbgc, "ba x 1 qnx 5 1000 \"command\"\n", VERR_DBGC_PARSE_INVALID_NUMBER);
463}
464
465
466static void testCodeView_bc(PDBGC pDbgc)
467{
468 RTTestISub("codeview - bc");
469}
470
471
472static void testCodeView_bd(PDBGC pDbgc)
473{
474 RTTestISub("codeview - bc");
475}
476
477
478static void testCodeView_be(PDBGC pDbgc)
479{
480 RTTestISub("codeview - be");
481}
482
483
484static void testCodeView_bl(PDBGC pDbgc)
485{
486 RTTestISub("codeview - bl");
487}
488
489
490static void testCodeView_bp(PDBGC pDbgc)
491{
492 RTTestISub("codeview - bp");
493}
494
495
496static void testCodeView_br(PDBGC pDbgc)
497{
498 RTTestISub("codeview - br");
499}
500
501
502static void testCodeView_d(PDBGC pDbgc)
503{
504 RTTestISub("codeview - d");
505}
506
507
508static void testCodeView_da(PDBGC pDbgc)
509{
510 RTTestISub("codeview - da");
511}
512
513
514static void testCodeView_db(PDBGC pDbgc)
515{
516 RTTestISub("codeview - db");
517}
518
519
520static void testCodeView_dd(PDBGC pDbgc)
521{
522 RTTestISub("codeview - dd");
523}
524
525
526static void testCodeView_dg(PDBGC pDbgc)
527{
528 RTTestISub("codeview - dg");
529}
530
531
532static void testCodeView_dga(PDBGC pDbgc)
533{
534 RTTestISub("codeview - dga");
535}
536
537
538static void testCodeView_di(PDBGC pDbgc)
539{
540 RTTestISub("codeview - di");
541}
542
543
544static void testCodeView_dia(PDBGC pDbgc)
545{
546 RTTestISub("codeview - dia");
547}
548
549
550static void testCodeView_dl(PDBGC pDbgc)
551{
552 RTTestISub("codeview - dl");
553}
554
555
556static void testCodeView_dla(PDBGC pDbgc)
557{
558 RTTestISub("codeview - dla");
559}
560
561
562static void testCodeView_dpd(PDBGC pDbgc)
563{
564 RTTestISub("codeview - dpd");
565}
566
567
568static void testCodeView_dpda(PDBGC pDbgc)
569{
570 RTTestISub("codeview - dpda");
571}
572
573
574static void testCodeView_dpdb(PDBGC pDbgc)
575{
576 RTTestISub("codeview - dpdb");
577}
578
579
580static void testCodeView_dpdg(PDBGC pDbgc)
581{
582 RTTestISub("codeview - dpdg");
583}
584
585
586static void testCodeView_dpdh(PDBGC pDbgc)
587{
588 RTTestISub("codeview - dpdh");
589}
590
591
592static void testCodeView_dph(PDBGC pDbgc)
593{
594 RTTestISub("codeview - dph");
595}
596
597
598static void testCodeView_dphg(PDBGC pDbgc)
599{
600 RTTestISub("codeview - dphg");
601}
602
603
604static void testCodeView_dphh(PDBGC pDbgc)
605{
606 RTTestISub("codeview - dphh");
607}
608
609
610static void testCodeView_dq(PDBGC pDbgc)
611{
612 RTTestISub("codeview - dq");
613}
614
615
616static void testCodeView_dt(PDBGC pDbgc)
617{
618 RTTestISub("codeview - dt");
619}
620
621
622static void testCodeView_dt16(PDBGC pDbgc)
623{
624 RTTestISub("codeview - dt16");
625}
626
627
628static void testCodeView_dt32(PDBGC pDbgc)
629{
630 RTTestISub("codeview - dt32");
631}
632
633
634static void testCodeView_dt64(PDBGC pDbgc)
635{
636 RTTestISub("codeview - dt64");
637}
638
639
640static void testCodeView_dw(PDBGC pDbgc)
641{
642 RTTestISub("codeview - dw");
643}
644
645
646static void testCodeView_eb(PDBGC pDbgc)
647{
648 RTTestISub("codeview - eb");
649}
650
651
652static void testCodeView_ew(PDBGC pDbgc)
653{
654 RTTestISub("codeview - ew");
655}
656
657
658static void testCodeView_ed(PDBGC pDbgc)
659{
660 RTTestISub("codeview - ed");
661}
662
663
664static void testCodeView_eq(PDBGC pDbgc)
665{
666 RTTestISub("codeview - eq");
667}
668
669
670static void testCodeView_g(PDBGC pDbgc)
671{
672 RTTestISub("codeview - g");
673}
674
675
676static void testCodeView_k(PDBGC pDbgc)
677{
678 RTTestISub("codeview - k");
679}
680
681
682static void testCodeView_kg(PDBGC pDbgc)
683{
684 RTTestISub("codeview - kg");
685}
686
687
688static void testCodeView_kh(PDBGC pDbgc)
689{
690 RTTestISub("codeview - kh");
691}
692
693
694static void testCodeView_lm(PDBGC pDbgc)
695{
696 RTTestISub("codeview - lm");
697}
698
699
700static void testCodeView_lmo(PDBGC pDbgc)
701{
702 RTTestISub("codeview - lmo");
703}
704
705
706static void testCodeView_ln(PDBGC pDbgc)
707{
708 RTTestISub("codeview - ln");
709}
710
711
712static void testCodeView_ls(PDBGC pDbgc)
713{
714 RTTestISub("codeview - ls");
715}
716
717
718static void testCodeView_m(PDBGC pDbgc)
719{
720 RTTestISub("codeview - m");
721}
722
723
724static void testCodeView_r(PDBGC pDbgc)
725{
726 RTTestISub("codeview - r");
727}
728
729
730static void testCodeView_rg(PDBGC pDbgc)
731{
732 RTTestISub("codeview - rg");
733}
734
735
736static void testCodeView_rg32(PDBGC pDbgc)
737{
738 RTTestISub("codeview - rg32");
739}
740
741
742static void testCodeView_rg64(PDBGC pDbgc)
743{
744 RTTestISub("codeview - rg64");
745}
746
747
748static void testCodeView_rh(PDBGC pDbgc)
749{
750 RTTestISub("codeview - rh");
751}
752
753
754static void testCodeView_rt(PDBGC pDbgc)
755{
756 RTTestISub("codeview - rt");
757}
758
759
760static void testCodeView_s(PDBGC pDbgc)
761{
762 RTTestISub("codeview - s");
763}
764
765
766static void testCodeView_sa(PDBGC pDbgc)
767{
768 RTTestISub("codeview - sa");
769}
770
771
772static void testCodeView_sb(PDBGC pDbgc)
773{
774 RTTestISub("codeview - sb");
775}
776
777
778static void testCodeView_sd(PDBGC pDbgc)
779{
780 RTTestISub("codeview - sd");
781}
782
783
784static void testCodeView_sq(PDBGC pDbgc)
785{
786 RTTestISub("codeview - sq");
787}
788
789
790static void testCodeView_su(PDBGC pDbgc)
791{
792 RTTestISub("codeview - su");
793}
794
795
796static void testCodeView_sw(PDBGC pDbgc)
797{
798 RTTestISub("codeview - sw");
799}
800
801
802static void testCodeView_t(PDBGC pDbgc)
803{
804 RTTestISub("codeview - t");
805}
806
807
808static void testCodeView_y(PDBGC pDbgc)
809{
810 RTTestISub("codeview - y");
811}
812
813
814static void testCodeView_u64(PDBGC pDbgc)
815{
816 RTTestISub("codeview - u64");
817}
818
819
820static void testCodeView_u32(PDBGC pDbgc)
821{
822 RTTestISub("codeview - u32");
823}
824
825
826static void testCodeView_u16(PDBGC pDbgc)
827{
828 RTTestISub("codeview - u16");
829}
830
831
832static void testCodeView_uv86(PDBGC pDbgc)
833{
834 RTTestISub("codeview - uv86");
835}
836
837
838/*
839 * Common commands.
840 */
841
842static void testCommon_bye_exit_quit(PDBGC pDbgc)
843{
844 RTTestISub("common - bye/exit/quit");
845 /* These have the same parameter descriptor and handler, the command really
846 just has a couple of aliases.*/
847 tstTry(pDbgc, "bye\n", VINF_SUCCESS);
848 tstTry(pDbgc, "bye x\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
849 tstTry(pDbgc, "bye 1\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
850 tstTry(pDbgc, "bye %bad:bad\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
851 tstTry(pDbgc, "exit\n", VINF_SUCCESS);
852 tstTry(pDbgc, "quit\n", VINF_SUCCESS);
853}
854
855
856static void testCommon_cpu(PDBGC pDbgc)
857{
858 RTTestISub("common - cpu");
859 tstTry(pDbgc, "cpu\n", VINF_SUCCESS);
860 tstTry(pDbgc, "cpu 1\n", VINF_SUCCESS);
861 tstTry(pDbgc, "cpu 1 1\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
862 tstTry(pDbgc, "cpu emt\n", VERR_DBGC_PARSE_INVALID_NUMBER);
863 tstTry(pDbgc, "cpu @eax\n", VINF_SUCCESS);
864 tstTry(pDbgc, "cpu %bad:bad\n", VERR_DBGC_PARSE_CONVERSION_FAILED);
865 tstTry(pDbgc, "cpu '1'\n", VERR_DBGC_PARSE_INVALID_NUMBER);
866}
867
868
869static void testCommon_echo(PDBGC pDbgc)
870{
871 RTTestISub("common - echo");
872 tstTry(pDbgc, "echo\n", VERR_DBGC_PARSE_TOO_FEW_ARGUMENTS);
873 tstTry(pDbgc, "echo 1\n", VINF_SUCCESS);
874 tstTryEx(pDbgc, "echo 1 2 3 4 5 6\n", VINF_SUCCESS, false, "1 2 3 4 5 6", -1);
875
876 /* The idea here is that since the prefered input is a string, we
877 definitely won't be confused by the number like beginning. */
878 tstTryEx(pDbgc, "echo 1234567890abcdefghijklmn\n", VINF_SUCCESS, false, "1234567890abcdefghijklmn", -1);
879
880 /* The idea here is that we'll perform the + operation and then convert the
881 result to a string (hex). */
882 tstTryEx(pDbgc, "echo 1 + 1\n", VINF_SUCCESS, false, "2", -1);
883 tstTryEx(pDbgc, "echo \"1 + 1\"\n", VINF_SUCCESS, false, "1 + 1", -1);
884
885 tstTryEx(pDbgc, "echo 0i10 + 6\n", VINF_SUCCESS, false, "10", -1);
886 tstTryEx(pDbgc, "echo \"0i10 + 6\"\n", VINF_SUCCESS, false, "0i10 + 6", -1);
887
888 tstTryEx(pDbgc, "echo %f000:0010\n", VINF_SUCCESS, false, "%00000000000f0010", -1);
889 tstTryEx(pDbgc, "echo \"%f000:0010\"\n", VINF_SUCCESS, false, "%f000:0010", -1);
890
891 tstTry(pDbgc, "echo %bad:bad\n", VERR_DBGC_PARSE_CONVERSION_FAILED);
892}
893
894
895static void testCommon_format(PDBGC pDbgc)
896{
897 RTTestISub("common - format");
898}
899
900
901static void testCommon_detect(PDBGC pDbgc)
902{
903 RTTestISub("common - detect");
904}
905
906
907static void testCommon_harakiri(PDBGC pDbgc)
908{
909 RTTestISub("common - harakiri");
910}
911
912
913static void testCommon_help(PDBGC pDbgc)
914{
915 RTTestISub("common - help");
916}
917
918
919static void testCommon_info(PDBGC pDbgc)
920{
921 RTTestISub("common - info");
922 tstTry(pDbgc, "info 12fg\n", VINF_SUCCESS);
923 tstTry(pDbgc, "info fflags argument\n", VINF_SUCCESS);
924}
925
926
927static void testCommon_loadimage(PDBGC pDbgc)
928{
929 RTTestISub("common - loadimage");
930}
931
932
933static void testCommon_loadmap(PDBGC pDbgc)
934{
935 RTTestISub("common - loadmap");
936}
937
938
939static void testCommon_loadplugin(PDBGC pDbgc)
940{
941 RTTestISub("common - loadplugin");
942}
943
944
945static void testCommon_loadseg(PDBGC pDbgc)
946{
947 RTTestISub("common - loadseg");
948}
949
950
951static void testCommon_loadsyms(PDBGC pDbgc)
952{
953 RTTestISub("common - loadsyms");
954}
955
956
957static void testCommon_loadvars(PDBGC pDbgc)
958{
959 RTTestISub("common - loadvars");
960}
961
962
963static void testCommon_log(PDBGC pDbgc)
964{
965 RTTestISub("common - log");
966}
967
968
969static void testCommon_logdest(PDBGC pDbgc)
970{
971 RTTestISub("common - logdest");
972}
973
974
975static void testCommon_logflags(PDBGC pDbgc)
976{
977 RTTestISub("common - logflags");
978}
979
980
981static void testCommon_runscript(PDBGC pDbgc)
982{
983 RTTestISub("common - runscript");
984}
985
986
987static void testCommon_set(PDBGC pDbgc)
988{
989 RTTestISub("common - set");
990}
991
992
993static void testCommon_showplugins(PDBGC pDbgc)
994{
995 RTTestISub("common - showplugins");
996}
997
998
999static void testCommon_showvars(PDBGC pDbgc)
1000{
1001 RTTestISub("common - showvars");
1002}
1003
1004
1005static void testCommon_stop(PDBGC pDbgc)
1006{
1007 RTTestISub("common - stop");
1008}
1009
1010
1011static void testCommon_unloadplugin(PDBGC pDbgc)
1012{
1013 RTTestISub("common - unloadplugin");
1014}
1015
1016
1017static void testCommon_unset(PDBGC pDbgc)
1018{
1019 RTTestISub("common - unset");
1020}
1021
1022
1023static void testCommon_writecore(PDBGC pDbgc)
1024{
1025 RTTestISub("common - writecore");
1026}
1027
1028
1029
1030/*
1031 * Basic tests.
1032 */
1033
1034static void testBasicsOddCases(PDBGC pDbgc)
1035{
1036 RTTestISub("Odd cases");
1037 tstTry(pDbgc, "r @rax\n", VINF_SUCCESS);
1038 tstTry(pDbgc, "r @eax\n", VINF_SUCCESS);
1039 tstTry(pDbgc, "r @ah\n", VINF_SUCCESS);
1040 tstTry(pDbgc, "r @notavalidregister\n", VERR_DBGF_REGISTER_NOT_FOUND);
1041}
1042
1043
1044static void testBasicsOperators(PDBGC pDbgc)
1045{
1046 RTTestISub("Operators");
1047 tstNumOp(pDbgc, "1", 1);
1048 tstNumOp(pDbgc, "1", 1);
1049 tstNumOp(pDbgc, "1", 1);
1050
1051 tstNumOp(pDbgc, "+1", 1);
1052 tstNumOp(pDbgc, "++++++1", 1);
1053
1054 tstNumOp(pDbgc, "-1", UINT64_MAX);
1055 tstNumOp(pDbgc, "--1", 1);
1056 tstNumOp(pDbgc, "---1", UINT64_MAX);
1057 tstNumOp(pDbgc, "----1", 1);
1058
1059 tstNumOp(pDbgc, "~0", UINT64_MAX);
1060 tstNumOp(pDbgc, "~1", UINT64_MAX-1);
1061 tstNumOp(pDbgc, "~~0", 0);
1062 tstNumOp(pDbgc, "~~1", 1);
1063
1064 tstNumOp(pDbgc, "!1", 0);
1065 tstNumOp(pDbgc, "!0", 1);
1066 tstNumOp(pDbgc, "!42", 0);
1067 tstNumOp(pDbgc, "!!42", 1);
1068 tstNumOp(pDbgc, "!!!42", 0);
1069 tstNumOp(pDbgc, "!!!!42", 1);
1070
1071 tstNumOp(pDbgc, "1 +1", 2);
1072 tstNumOp(pDbgc, "1 + 1", 2);
1073 tstNumOp(pDbgc, "1+1", 2);
1074 tstNumOp(pDbgc, "1+ 1", 2);
1075
1076 tstNumOp(pDbgc, "1 - 1", 0);
1077 tstNumOp(pDbgc, "99 - 90", 9);
1078
1079 tstNumOp(pDbgc, "2 * 2", 4);
1080
1081 tstNumOp(pDbgc, "2 / 2", 1);
1082 tstNumOp(pDbgc, "2 / 0", UINT64_MAX);
1083 tstNumOp(pDbgc, "0i1024 / 0i4", 256);
1084
1085 tstNumOp(pDbgc, "8 mod 7", 1);
1086
1087 tstNumOp(pDbgc, "1<<1", 2);
1088 tstNumOp(pDbgc, "1<<0i32", UINT64_C(0x0000000100000000));
1089 tstNumOp(pDbgc, "1<<0i48", UINT64_C(0x0001000000000000));
1090 tstNumOp(pDbgc, "1<<0i63", UINT64_C(0x8000000000000000));
1091
1092 tstNumOp(pDbgc, "fedcba0987654321>>0i04", UINT64_C(0x0fedcba098765432));
1093 tstNumOp(pDbgc, "fedcba0987654321>>0i32", UINT64_C(0xfedcba09));
1094 tstNumOp(pDbgc, "fedcba0987654321>>0i48", UINT64_C(0x0000fedc));
1095
1096 tstNumOp(pDbgc, "0ef & 4", 4);
1097 tstNumOp(pDbgc, "01234567891 & fff", UINT64_C(0x00000000891));
1098 tstNumOp(pDbgc, "01234567891 & ~fff", UINT64_C(0x01234567000));
1099
1100 tstNumOp(pDbgc, "1 | 1", 1);
1101 tstNumOp(pDbgc, "0 | 4", 4);
1102 tstNumOp(pDbgc, "4 | 0", 4);
1103 tstNumOp(pDbgc, "4 | 4", 4);
1104 tstNumOp(pDbgc, "1 | 4 | 2", 7);
1105
1106 tstNumOp(pDbgc, "1 ^ 1", 0);
1107 tstNumOp(pDbgc, "1 ^ 0", 1);
1108 tstNumOp(pDbgc, "0 ^ 1", 1);
1109 tstNumOp(pDbgc, "3 ^ 1", 2);
1110 tstNumOp(pDbgc, "7 ^ 3", 4);
1111
1112 tstNumOp(pDbgc, "7 || 3", 1);
1113 tstNumOp(pDbgc, "1 || 0", 1);
1114 tstNumOp(pDbgc, "0 || 1", 1);
1115 tstNumOp(pDbgc, "0 || 0", 0);
1116
1117 tstNumOp(pDbgc, "0 && 0", 0);
1118 tstNumOp(pDbgc, "1 && 0", 0);
1119 tstNumOp(pDbgc, "0 && 1", 0);
1120 tstNumOp(pDbgc, "1 && 1", 1);
1121 tstNumOp(pDbgc, "4 && 1", 1);
1122}
1123
1124
1125static void testBasicsFundametalParsing(PDBGC pDbgc)
1126{
1127 RTTestISub("Fundamental parsing");
1128 tstTry(pDbgc, "stop\n", VINF_SUCCESS);
1129 tstTry(pDbgc, "format 1\n", VINF_SUCCESS);
1130 tstTry(pDbgc, "format \n", VERR_DBGC_PARSE_TOO_FEW_ARGUMENTS);
1131 tstTry(pDbgc, "format 0 1 23 4\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
1132 tstTry(pDbgc, "format 'x'\n", VINF_SUCCESS);
1133 tstTry(pDbgc, "format 'x' 'x'\n", VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS);
1134 tstTry(pDbgc, "format 'x''x'\n", VINF_SUCCESS);
1135 tstTry(pDbgc, "format 'x'\"x\"\n", VERR_DBGC_PARSE_EXPECTED_BINARY_OP);
1136 tstTry(pDbgc, "format 'x'1\n", VERR_DBGC_PARSE_EXPECTED_BINARY_OP);
1137 tstTry(pDbgc, "format (1)1\n", VERR_DBGC_PARSE_EXPECTED_BINARY_OP);
1138 tstTry(pDbgc, "format (1)(1)\n", VERR_DBGC_PARSE_EXPECTED_BINARY_OP);
1139 tstTry(pDbgc, "format (1)''\n", VERR_DBGC_PARSE_EXPECTED_BINARY_OP);
1140 tstTry(pDbgc, "format nosuchfunction(1)\n", VERR_DBGC_PARSE_FUNCTION_NOT_FOUND);
1141 tstTry(pDbgc, "format nosuchfunction(1,2,3)\n", VERR_DBGC_PARSE_FUNCTION_NOT_FOUND);
1142 tstTry(pDbgc, "format nosuchfunction()\n", VERR_DBGC_PARSE_FUNCTION_NOT_FOUND);
1143 tstTry(pDbgc, "format randu32()\n", VINF_SUCCESS);
1144 tstTryEx(pDbgc, "format %0\n", VINF_SUCCESS, false, "Guest flat address: %00000000", -1);
1145 tstTryEx(pDbgc, "format %eax\n", VINF_SUCCESS, false, "Guest flat address: %cafebabe", -1);
1146 tstTry(pDbgc, "sa 3 23 4 'q' \"21123123\" 'b' \n", VINF_SUCCESS);
1147 tstTry(pDbgc, "sa 3,23, 4,'q' ,\"21123123\" , 'b' \n", VINF_SUCCESS);
1148}
1149
1150
1151int main()
1152{
1153 /*
1154 * Init.
1155 */
1156 int rc = RTTestInitAndCreate("tstDBGCParser", &g_hTest);
1157 if (rc)
1158 return rc;
1159 RTTestBanner(g_hTest);
1160
1161 /*
1162 * Create a DBGC instance.
1163 */
1164 RTTestSub(g_hTest, "dbgcCreate");
1165 PDBGC pDbgc;
1166 rc = dbgcCreate(&pDbgc, &g_tstBack, 0);
1167 if (RT_SUCCESS(rc))
1168 {
1169 pDbgc->pVM = (PVM)pDbgc;
1170 rc = dbgcProcessInput(pDbgc, true /* fNoExecute */);
1171 tstCompleteOutput();
1172 if (RT_SUCCESS(rc))
1173 {
1174 /*
1175 * Perform basic tests first.
1176 */
1177 testBasicsFundametalParsing(pDbgc);
1178 if (RTTestErrorCount(g_hTest) == 0)
1179 testBasicsOperators(pDbgc);
1180 if (RTTestErrorCount(g_hTest) == 0)
1181 testBasicsOddCases(pDbgc);
1182
1183 /*
1184 * Test commands.
1185 */
1186 if (RTTestErrorCount(g_hTest) == 0)
1187 {
1188 testCodeView_ba(pDbgc);
1189 testCodeView_bc(pDbgc);
1190 testCodeView_bd(pDbgc);
1191 testCodeView_be(pDbgc);
1192 testCodeView_bl(pDbgc);
1193 testCodeView_bp(pDbgc);
1194 testCodeView_br(pDbgc);
1195 testCodeView_d(pDbgc);
1196 testCodeView_da(pDbgc);
1197 testCodeView_db(pDbgc);
1198 testCodeView_dd(pDbgc);
1199 testCodeView_dg(pDbgc);
1200 testCodeView_dga(pDbgc);
1201 testCodeView_di(pDbgc);
1202 testCodeView_dia(pDbgc);
1203 testCodeView_dl(pDbgc);
1204 testCodeView_dla(pDbgc);
1205 testCodeView_dpd(pDbgc);
1206 testCodeView_dpda(pDbgc);
1207 testCodeView_dpdb(pDbgc);
1208 testCodeView_dpdg(pDbgc);
1209 testCodeView_dpdh(pDbgc);
1210 testCodeView_dph(pDbgc);
1211 testCodeView_dphg(pDbgc);
1212 testCodeView_dphh(pDbgc);
1213 testCodeView_dq(pDbgc);
1214 testCodeView_dt(pDbgc);
1215 testCodeView_dt16(pDbgc);
1216 testCodeView_dt32(pDbgc);
1217 testCodeView_dt64(pDbgc);
1218 testCodeView_dw(pDbgc);
1219 testCodeView_eb(pDbgc);
1220 testCodeView_ew(pDbgc);
1221 testCodeView_ed(pDbgc);
1222 testCodeView_eq(pDbgc);
1223 testCodeView_g(pDbgc);
1224 testCodeView_k(pDbgc);
1225 testCodeView_kg(pDbgc);
1226 testCodeView_kh(pDbgc);
1227 testCodeView_lm(pDbgc);
1228 testCodeView_lmo(pDbgc);
1229 testCodeView_ln(pDbgc);
1230 testCodeView_ls(pDbgc);
1231 testCodeView_m(pDbgc);
1232 testCodeView_r(pDbgc);
1233 testCodeView_rg(pDbgc);
1234 testCodeView_rg32(pDbgc);
1235 testCodeView_rg64(pDbgc);
1236 testCodeView_rh(pDbgc);
1237 testCodeView_rt(pDbgc);
1238 testCodeView_s(pDbgc);
1239 testCodeView_sa(pDbgc);
1240 testCodeView_sb(pDbgc);
1241 testCodeView_sd(pDbgc);
1242 testCodeView_sq(pDbgc);
1243 testCodeView_su(pDbgc);
1244 testCodeView_sw(pDbgc);
1245 testCodeView_t(pDbgc);
1246 testCodeView_y(pDbgc);
1247 testCodeView_u64(pDbgc);
1248 testCodeView_u32(pDbgc);
1249 testCodeView_u16(pDbgc);
1250 testCodeView_uv86(pDbgc);
1251
1252 testCommon_bye_exit_quit(pDbgc);
1253 testCommon_cpu(pDbgc);
1254 testCommon_echo(pDbgc);
1255 testCommon_format(pDbgc);
1256 testCommon_detect(pDbgc);
1257 testCommon_harakiri(pDbgc);
1258 testCommon_help(pDbgc);
1259 testCommon_info(pDbgc);
1260 testCommon_loadimage(pDbgc);
1261 testCommon_loadmap(pDbgc);
1262 testCommon_loadplugin(pDbgc);
1263 testCommon_loadseg(pDbgc);
1264 testCommon_loadsyms(pDbgc);
1265 testCommon_loadvars(pDbgc);
1266 testCommon_log(pDbgc);
1267 testCommon_logdest(pDbgc);
1268 testCommon_logflags(pDbgc);
1269 testCommon_runscript(pDbgc);
1270 testCommon_set(pDbgc);
1271 testCommon_showplugins(pDbgc);
1272 testCommon_showvars(pDbgc);
1273 testCommon_stop(pDbgc);
1274 testCommon_unloadplugin(pDbgc);
1275 testCommon_unset(pDbgc);
1276 testCommon_writecore(pDbgc);
1277 }
1278 }
1279
1280 dbgcDestroy(pDbgc);
1281 }
1282
1283 /*
1284 * Summary
1285 */
1286 return RTTestSummaryAndDestroy(g_hTest);
1287}
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