VirtualBox

source: vbox/trunk/src/VBox/Disassembler/testcase/tstDisasmArmv8-1.cpp@ 106770

最後變更 在這個檔案從106770是 106770,由 vboxsync 提交於 5 月 前

Disassembler: Decode load/store memory tags instructions, bugref:10394

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 28.7 KB
 
1/* $Id: tstDisasmArmv8-1.cpp 106770 2024-10-29 13:09:50Z vboxsync $ */
2/** @file
3 * VBox disassembler - Testcase for ARMv8 A64
4 */
5
6/*
7 * Copyright (C) 2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.alldomusa.eu.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define VBOX_DIS_WITH_ARMV8
33#include <VBox/dis.h>
34#include <VBox/err.h>
35#include <iprt/test.h>
36#include <iprt/ctype.h>
37#include <iprt/string.h>
38#include <iprt/err.h>
39#include <iprt/script.h>
40#include <iprt/sg.h>
41#include <iprt/stream.h>
42
43#ifdef TST_DISASM_WITH_CAPSTONE_DISASSEMBLER
44# include "/opt/homebrew/include/capstone/capstone.h"
45#endif
46
47#include "tstDisasmArmv8-1-tests.h"
48
49typedef struct TESTRDR
50{
51 RTSGSEG aSegs[3];
52 RTSGBUF SgBuf;
53} TESTRDR;
54typedef TESTRDR *PTESTRDR;
55
56DECLASM(int) TestProcA64(void);
57DECLASM(int) TestProcA64_EndProc(void);
58
59
60static DECLCALLBACK(int) rtScriptLexParseNumber(RTSCRIPTLEX hScriptLex, char ch, PRTSCRIPTLEXTOKEN pToken, void *pvUser)
61{
62 RT_NOREF(ch, pvUser);
63 return RTScriptLexScanNumber(hScriptLex, 0 /*uBase*/, false /*fAllowReal*/, pToken);
64}
65
66
67static const char *s_aszSingleStart[] =
68{
69 ";",
70 NULL
71};
72
73
74static const char *s_aszMultiStart[] =
75{
76 "/*",
77 NULL
78};
79
80
81static const char *s_aszMultiEnd[] =
82{
83 "*/",
84 NULL
85};
86
87
88static const RTSCRIPTLEXTOKMATCH s_aMatches[] =
89{
90 /* Begin of stuff which will get ignored in the semantic matching. */
91 { RT_STR_TUPLE(".private_extern"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 },
92 { RT_STR_TUPLE(".cpu"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 },
93 { RT_STR_TUPLE("generic+mte"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 },
94 { RT_STR_TUPLE("_testproca64"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 },
95 { RT_STR_TUPLE("_testproca64_endproc"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 },
96 { RT_STR_TUPLE(":"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 },
97 /* End of stuff which will get ignored in the semantic matching. */
98
99 { RT_STR_TUPLE(","), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, 0 },
100 { RT_STR_TUPLE("."), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, 0 },
101 { RT_STR_TUPLE("["), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, 0 },
102 { RT_STR_TUPLE("]"), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, 0 },
103 { RT_STR_TUPLE("!"), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, 0 },
104 { NULL, 0, RTSCRIPTLEXTOKTYPE_INVALID, false, 0 }
105};
106
107
108static const RTSCRIPTLEXRULE s_aRules[] =
109{
110 { '#', '#', RTSCRIPT_LEX_RULE_CONSUME, rtScriptLexParseNumber, NULL},
111 { '0', '9', RTSCRIPT_LEX_RULE_CONSUME, rtScriptLexParseNumber, NULL},
112 { 'a', 'z', RTSCRIPT_LEX_RULE_CONSUME, RTScriptLexScanIdentifier, NULL},
113 { 'A', 'Z', RTSCRIPT_LEX_RULE_CONSUME, RTScriptLexScanIdentifier, NULL},
114 { '_', '_', RTSCRIPT_LEX_RULE_CONSUME, RTScriptLexScanIdentifier, NULL},
115 { '\0', '\0', RTSCRIPT_LEX_RULE_DEFAULT, NULL, NULL}
116};
117
118
119static const RTSCRIPTLEXCFG s_LexCfg =
120{
121 /** pszName */
122 "ARMv8Dis",
123 /** pszDesc */
124 "ARMv8 disassembler lexer",
125 /** fFlags */
126 RTSCRIPT_LEX_CFG_F_CASE_INSENSITIVE,
127 /** pszWhitespace */
128 NULL,
129 /** pszNewline */
130 NULL,
131 /** papszCommentMultiStart */
132 s_aszMultiStart,
133 /** papszCommentMultiEnd */
134 s_aszMultiEnd,
135 /** papszCommentSingleStart */
136 s_aszSingleStart,
137 /** paTokMatches */
138 s_aMatches,
139 /** paRules */
140 s_aRules,
141 /** pfnProdDef */
142 NULL,
143 /** pfnProdDefUser */
144 NULL
145};
146
147
148static DECLCALLBACK(int) testDisasmLexerRead(RTSCRIPTLEX hScriptLex, size_t offBuf, char *pchCur,
149 size_t cchBuf, size_t *pcchRead, void *pvUser)
150{
151 RT_NOREF(hScriptLex, offBuf);
152
153 PTESTRDR pRdr = (PTESTRDR)pvUser;
154 size_t cbCopied = RTSgBufCopyToBuf(&pRdr->SgBuf, pchCur, cchBuf * sizeof(char));
155
156 *pcchRead = cbCopied * sizeof(char);
157 if (!cbCopied)
158 return VINF_EOF;
159
160 return VINF_SUCCESS;
161}
162
163
164static void testDisas(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode,
165 const unsigned char *pbSrc, unsigned cbSrc)
166{
167 RTTestISub(pszSub);
168
169 RTSCRIPTLEX hLexSource = NULL;
170 TESTRDR Rdr;
171
172 Rdr.aSegs[0].pvSeg = (void *)pbSrc;
173 Rdr.aSegs[0].cbSeg = cbSrc;
174 RTSgBufInit(&Rdr.SgBuf, &Rdr.aSegs[0], 1);
175 int rc = RTScriptLexCreateFromReader(&hLexSource, testDisasmLexerRead,
176 NULL /*pfnDtor*/, &Rdr /*pvUser*/, cbSrc,
177 NULL /*phStrCacheId*/, NULL /*phStrCacheStringLit*/,
178 &s_LexCfg);
179 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
180 if (RT_FAILURE(rc))
181 return; /* Can't do our work if this fails. */
182
183 PCRTSCRIPTLEXTOKEN pTokSource;
184 rc = RTScriptLexQueryToken(hLexSource, &pTokSource);
185 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
186
187 size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs;
188 for (size_t off = 0; off < cbInstrs;)
189 {
190 DISSTATE Dis;
191 uint32_t cb = 1;
192#ifndef DIS_CORE_ONLY
193 uint32_t const cErrBefore = RTTestIErrorCount();
194 char szOutput[256] = {0};
195
196 /*
197 * Can't use DISInstrToStr() here as it would add addresses and opcode bytes
198 * which would trip the semantic matching later on.
199 */
200 rc = DISInstrEx((uintptr_t)&pabInstrs[off], enmDisCpuMode, DISOPTYPE_ALL,
201 NULL /*pfnReadBytes*/, NULL /*pvUser*/, &Dis, &cb);
202 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
203 RTTESTI_CHECK(cb == Dis.cbInstr);
204 RTTESTI_CHECK(cb == sizeof(uint32_t));
205
206 if (RT_SUCCESS(rc))
207 {
208 size_t cch = 0;
209
210 switch (enmDisCpuMode)
211 {
212 case DISCPUMODE_ARMV8_A64:
213 case DISCPUMODE_ARMV8_A32:
214 case DISCPUMODE_ARMV8_T32:
215 cch = DISFormatArmV8Ex(&Dis, &szOutput[0], sizeof(szOutput),
216 DIS_FMT_FLAGS_RELATIVE_BRANCH,
217 NULL /*pfnGetSymbol*/, NULL /*pvUser*/);
218 break;
219 default:
220 AssertReleaseFailed(); /* Testcase error. */
221 break;
222 }
223
224 szOutput[cch] = '\0';
225 RTStrStripR(szOutput);
226 RTTESTI_CHECK(szOutput[0]);
227 if (szOutput[0])
228 {
229 /* Build the lexer and compare that it semantically is equal to the source input. */
230 RTSCRIPTLEX hLexDis = NULL;
231 rc = RTScriptLexCreateFromString(&hLexDis, szOutput, NULL /*phStrCacheId*/,
232 NULL /*phStrCacheStringLit*/, &s_LexCfg);
233 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
234 if (RT_SUCCESS(rc))
235 {
236 PCRTSCRIPTLEXTOKEN pTokDis;
237 rc = RTScriptLexQueryToken(hLexDis, &pTokDis);
238 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
239
240 /*
241 * Skip over any keyword tokens in the source lexer because these
242 * are not part of the disassembly.
243 */
244 while (pTokSource->enmType == RTSCRIPTLEXTOKTYPE_KEYWORD)
245 pTokSource = RTScriptLexConsumeToken(hLexSource);
246
247 /* Now compare the token streams until we hit EOS in the disassembly lexer. */
248 do
249 {
250 RTTESTI_CHECK(pTokSource->enmType == pTokDis->enmType);
251 if (pTokSource->enmType == pTokDis->enmType)
252 {
253 switch (pTokSource->enmType)
254 {
255 case RTSCRIPTLEXTOKTYPE_IDENTIFIER:
256 {
257 int iCmp = strcmp(pTokSource->Type.Id.pszIde, pTokDis->Type.Id.pszIde);
258 RTTESTI_CHECK(!iCmp);
259 if (iCmp)
260 RTTestIFailureDetails("<IDE{%u.%u, %u.%u}, %s != %s>\n",
261 pTokSource->PosStart.iLine, pTokSource->PosStart.iCh,
262 pTokSource->PosEnd.iLine, pTokSource->PosEnd.iCh,
263 pTokSource->Type.Id.pszIde, pTokDis->Type.Id.pszIde);
264 break;
265 }
266 case RTSCRIPTLEXTOKTYPE_NUMBER:
267 RTTESTI_CHECK(pTokSource->Type.Number.enmType == pTokDis->Type.Number.enmType);
268 if (pTokSource->Type.Number.enmType == pTokDis->Type.Number.enmType)
269 {
270 switch (pTokSource->Type.Number.enmType)
271 {
272 case RTSCRIPTLEXTOKNUMTYPE_NATURAL:
273 {
274 RTTESTI_CHECK(pTokSource->Type.Number.Type.u64 == pTokDis->Type.Number.Type.u64);
275 if (pTokSource->Type.Number.Type.u64 != pTokDis->Type.Number.Type.u64)
276 RTTestIFailureDetails("<NUM{%u.%u, %u.%u} %RU64 != %RU64>\n",
277 pTokSource->PosStart.iLine, pTokSource->PosStart.iCh,
278 pTokSource->PosEnd.iLine, pTokSource->PosEnd.iCh,
279 pTokSource->Type.Number.Type.u64, pTokDis->Type.Number.Type.u64);
280 break;
281 }
282 case RTSCRIPTLEXTOKNUMTYPE_INTEGER:
283 {
284 RTTESTI_CHECK(pTokSource->Type.Number.Type.i64 == pTokDis->Type.Number.Type.i64);
285 if (pTokSource->Type.Number.Type.i64 != pTokDis->Type.Number.Type.i64)
286 RTTestIFailureDetails("<NUM{%u.%u, %u.%u} %RI64 != %RI64>\n",
287 pTokSource->PosStart.iLine, pTokSource->PosStart.iCh,
288 pTokSource->PosEnd.iLine, pTokSource->PosEnd.iCh,
289 pTokSource->Type.Number.Type.i64, pTokDis->Type.Number.Type.i64);
290 break;
291 }
292 case RTSCRIPTLEXTOKNUMTYPE_REAL:
293 default:
294 AssertReleaseFailed();
295 }
296 }
297 else
298 RTTestIFailureDetails("<NUM{%u.%u, %u.%u} %u != %u>\n",
299 pTokSource->PosStart.iLine, pTokSource->PosStart.iCh,
300 pTokSource->PosEnd.iLine, pTokSource->PosEnd.iCh,
301 pTokSource->Type.Number.enmType, pTokDis->Type.Number.enmType);
302 break;
303 case RTSCRIPTLEXTOKTYPE_PUNCTUATOR:
304 {
305 int iCmp = strcmp(pTokSource->Type.Punctuator.pPunctuator->pszMatch,
306 pTokDis->Type.Punctuator.pPunctuator->pszMatch);
307 RTTESTI_CHECK(!iCmp);
308 if (iCmp)
309 RTTestIFailureDetails("<PUNCTUATOR{%u.%u, %u.%u}, %s != %s>\n",
310 pTokSource->PosStart.iLine, pTokSource->PosStart.iCh,
311 pTokSource->PosEnd.iLine, pTokSource->PosEnd.iCh,
312 pTokSource->Type.Punctuator.pPunctuator->pszMatch,
313 pTokDis->Type.Punctuator.pPunctuator->pszMatch);
314 break;
315 }
316
317 /* These should never occur and indicate an issue in the lexer. */
318 case RTSCRIPTLEXTOKTYPE_KEYWORD:
319 RTTestIFailureDetails("<KEYWORD{%u.%u, %u.%u}, %s>\n",
320 pTokSource->PosStart.iLine, pTokSource->PosStart.iCh,
321 pTokSource->PosEnd.iLine, pTokSource->PosEnd.iCh,
322 pTokSource->Type.Keyword.pKeyword->pszMatch);
323 break;
324 case RTSCRIPTLEXTOKTYPE_STRINGLIT:
325 RTTestIFailureDetails("<STRINGLIT{%u.%u, %u.%u}, %s>\n",
326 pTokSource->PosStart.iLine, pTokSource->PosStart.iCh,
327 pTokSource->PosEnd.iLine, pTokSource->PosEnd.iCh,
328 pTokSource->Type.StringLit.pszString);
329 break;
330 case RTSCRIPTLEXTOKTYPE_OPERATOR:
331 RTTestIFailureDetails("<OPERATOR{%u.%u, %u.%u}, %s>\n",
332 pTokSource->PosStart.iLine, pTokSource->PosStart.iCh,
333 pTokSource->PosEnd.iLine, pTokSource->PosEnd.iCh,
334 pTokSource->Type.Operator.pOp->pszMatch);
335 break;
336 case RTSCRIPTLEXTOKTYPE_INVALID:
337 RTTestIFailureDetails("<INVALID>\n");
338 break;
339 case RTSCRIPTLEXTOKTYPE_ERROR:
340 RTTestIFailureDetails("<ERROR{%u.%u, %u.%u}> %s\n",
341 pTokSource->PosStart.iLine, pTokSource->PosStart.iCh,
342 pTokSource->PosEnd.iLine, pTokSource->PosEnd.iCh,
343 pTokSource->Type.Error.pErr->pszMsg);
344 break;
345 case RTSCRIPTLEXTOKTYPE_EOS:
346 RTTestIFailureDetails("<EOS>\n");
347 break;
348 default:
349 AssertFailed();
350 }
351 }
352 else
353 RTTestIFailureDetails("pTokSource->enmType=%u pTokDis->enmType=%u\n",
354 pTokSource->enmType, pTokDis->enmType);
355
356 /*
357 * Abort on error as the streams are now out of sync and matching will not work
358 * anymore producing lots of noise.
359 */
360 if (cErrBefore != RTTestIErrorCount())
361 break;
362
363 /* Advance to the next token. */
364 pTokDis = RTScriptLexConsumeToken(hLexDis);
365 Assert(pTokDis);
366
367 pTokSource = RTScriptLexConsumeToken(hLexSource);
368 Assert(pTokSource);
369 } while (pTokDis->enmType != RTSCRIPTLEXTOKTYPE_EOS);
370
371 RTScriptLexDestroy(hLexDis);
372 }
373 }
374 if (cErrBefore != RTTestIErrorCount())
375 {
376 RTTestIFailureDetails("rc=%Rrc, off=%#x (%u) cbInstr=%u enmDisCpuMode=%d\n",
377 rc, off, off, Dis.cbInstr, enmDisCpuMode);
378 RTTestIPrintf(RTTESTLVL_ALWAYS, "%s\n", szOutput);
379 break;
380 }
381
382 /* Do the output formatting again, now with all the addresses and opcode bytes. */
383 DISFormatArmV8Ex(&Dis, szOutput, sizeof(szOutput),
384 DIS_FMT_FLAGS_BYTES_LEFT | DIS_FMT_FLAGS_BYTES_BRACKETS | DIS_FMT_FLAGS_BYTES_SPACED
385 | DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_ADDR_LEFT,
386 NULL /*pfnGetSymbol*/, NULL /*pvUser*/);
387 RTStrStripR(szOutput);
388 RTTESTI_CHECK(szOutput[0]);
389 RTTestIPrintf(RTTESTLVL_ALWAYS, "%s\n", szOutput);
390 }
391 else
392 break;
393
394 /* Check with size-only. */
395 uint32_t cbOnly = 1;
396 DISSTATE DisOnly;
397 rc = DISInstrWithPrefetchedBytes((uintptr_t)&pabInstrs[off], enmDisCpuMode, 0 /*fFilter - none */,
398 Dis.Instr.ab, Dis.cbCachedInstr, NULL, NULL, &DisOnly, &cbOnly);
399
400 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
401 RTTESTI_CHECK(cbOnly == DisOnly.cbInstr);
402 RTTESTI_CHECK_MSG(cbOnly == cb, ("%#x vs %#x\n", cbOnly, cb));
403
404#else /* DIS_CORE_ONLY */
405 rc = DISInstr(&pabInstrs[off], enmDisCpuMode, &Dis, &cb);
406 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
407 RTTESTI_CHECK(cb == Dis.cbInstr);
408#endif /* DIS_CORE_ONLY */
409
410 off += cb;
411 }
412
413 RTScriptLexDestroy(hLexSource);
414}
415
416
417#if defined(TST_DISASM_WITH_CAPSTONE_DISASSEMBLER) && !defined(DIS_CORE_ONLY)
418/**
419 * Testcase generating all possible 32-bit instruction values and checking our disassembler
420 * for compliance against the capstone disassembler (based on LLVM).
421 */
422static void testDisasComplianceAgaistCapstone(void)
423{
424 /** @todo SMP */
425
426 csh hDisasm = ~(size_t)0;
427 cs_err rcCs = cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &hDisasm);
428 AssertMsgReturnVoid(rcCs == CS_ERR_OK, ("%d (%#x)\n", rcCs, rcCs));
429
430 char szOutput[256] = {0};
431
432 for (uint32_t u32Insn = 0; u32Insn < UINT32_MAX; u32Insn++)
433 {
434 cs_insn *pInstr;
435 size_t cInstrs = cs_disasm(hDisasm, (const uint8_t *)&u32Insn, sizeof(u32Insn),
436 (uintptr_t)&u32Insn, 1, &pInstr);
437
438 DISSTATE Dis;
439 uint32_t cb = 1;
440
441 /*
442 * Can't use DISInstrToStr() here as it would add addresses and opcode bytes
443 * which would trip the semantic matching later on.
444 */
445 int rc = DISInstrEx((uintptr_t)&u32Insn, DISCPUMODE_ARMV8_A64, DISOPTYPE_ALL,
446 NULL /*pfnReadBytes*/, NULL /*pvUser*/, &Dis, &cb);
447 if (rc == VERR_DIS_INVALID_OPCODE)
448 {
449 /* Check whether capstone could successfully disassembler the instruction. */
450 if (cInstrs)
451 {
452 RTTestIFailureDetails("%#08RX32: rcDis==VERR_DIS_INVALID_OPCODE, capstone=%s %s\n",
453 u32Insn, pInstr->mnemonic, pInstr->op_str);
454 }
455 /* else: Invalid encoding from both disassemblers, continue. */
456 }
457 else
458 {
459 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
460 RTTESTI_CHECK(cb == Dis.cbInstr);
461 RTTESTI_CHECK(cb == sizeof(uint32_t));
462
463 size_t cch = DISFormatArmV8Ex(&Dis, &szOutput[0], sizeof(szOutput),
464 DIS_FMT_FLAGS_RELATIVE_BRANCH,
465 NULL /*pfnGetSymbol*/, NULL /*pvUser*/);
466 Assert(cch);
467
468 szOutput[cch] = '\0';
469 RTStrStripR(szOutput);
470 RTTESTI_CHECK(szOutput[0]);
471
472 if (cInstrs > 0)
473 {
474 /* Compare semantically. */
475
476 RTSCRIPTLEX hLexCapstone = NULL;
477 TESTRDR Rdr;
478
479 Rdr.aSegs[0].pvSeg = pInstr->mnemonic;
480 Rdr.aSegs[0].cbSeg = strlen(pInstr->mnemonic);
481 Rdr.aSegs[1].pvSeg = (void *)" ";
482 Rdr.aSegs[1].cbSeg = 1;
483 Rdr.aSegs[2].pvSeg = pInstr->op_str;
484 Rdr.aSegs[2].cbSeg = strlen(pInstr->op_str);
485 RTSgBufInit(&Rdr.SgBuf, &Rdr.aSegs[0], 3);
486 rc = RTScriptLexCreateFromReader(&hLexCapstone, testDisasmLexerRead,
487 NULL /*pfnDtor*/, &Rdr /*pvUser*/, 0 /*cchBuf*/,
488 NULL /*phStrCacheId*/, NULL /*phStrCacheStringLit*/,
489 &s_LexCfg);
490 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
491
492 /* Build the lexer and compare that it semantically is equal to the source input. */
493 RTSCRIPTLEX hLexDis = NULL;
494 rc = RTScriptLexCreateFromString(&hLexDis, szOutput, NULL /*phStrCacheId*/,
495 NULL /*phStrCacheStringLit*/, &s_LexCfg);
496 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
497 if (RT_SUCCESS(rc))
498 {
499 PCRTSCRIPTLEXTOKEN pTokDis;
500 rc = RTScriptLexQueryToken(hLexDis, &pTokDis);
501 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
502
503 PCRTSCRIPTLEXTOKEN pTokCapstone;
504 rc = RTScriptLexQueryToken(hLexCapstone, &pTokCapstone);
505 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
506
507 /* Now compare the token streams until we hit EOS in the disassembly lexer. */
508 bool fFailed = false;
509 do
510 {
511 if (pTokCapstone->enmType == pTokDis->enmType)
512 {
513 switch (pTokCapstone->enmType)
514 {
515 case RTSCRIPTLEXTOKTYPE_IDENTIFIER:
516 {
517 int iCmp = strcmp(pTokCapstone->Type.Id.pszIde, pTokDis->Type.Id.pszIde);
518 if (iCmp)
519 fFailed = true;
520 break;
521 }
522 case RTSCRIPTLEXTOKTYPE_NUMBER:
523 if (pTokCapstone->Type.Number.enmType == pTokDis->Type.Number.enmType)
524 {
525 switch (pTokCapstone->Type.Number.enmType)
526 {
527 case RTSCRIPTLEXTOKNUMTYPE_NATURAL:
528 {
529 if (pTokCapstone->Type.Number.Type.u64 != pTokDis->Type.Number.Type.u64)
530 fFailed = true;
531 break;
532 }
533 case RTSCRIPTLEXTOKNUMTYPE_INTEGER:
534 {
535 if (pTokCapstone->Type.Number.Type.i64 != pTokDis->Type.Number.Type.i64)
536 fFailed = true;
537 break;
538 }
539 case RTSCRIPTLEXTOKNUMTYPE_REAL:
540 default:
541 AssertReleaseFailed();
542 }
543 }
544 else
545 fFailed = true;
546 break;
547 case RTSCRIPTLEXTOKTYPE_PUNCTUATOR:
548 {
549 int iCmp = strcmp(pTokCapstone->Type.Punctuator.pPunctuator->pszMatch,
550 pTokDis->Type.Punctuator.pPunctuator->pszMatch);
551 if (iCmp)
552 fFailed = true;
553 break;
554 }
555
556 /* These should never occur and indicate an issue in the lexer. */
557 case RTSCRIPTLEXTOKTYPE_KEYWORD:
558 case RTSCRIPTLEXTOKTYPE_STRINGLIT:
559 case RTSCRIPTLEXTOKTYPE_OPERATOR:
560 case RTSCRIPTLEXTOKTYPE_INVALID:
561 case RTSCRIPTLEXTOKTYPE_ERROR:
562 case RTSCRIPTLEXTOKTYPE_EOS:
563 fFailed = true;
564 break;
565 default:
566 AssertFailed();
567 }
568 }
569 else
570 fFailed = true;
571
572 /* Abort on error. */
573 if (fFailed)
574 break;
575
576 /* Advance to the next token. */
577 pTokDis = RTScriptLexConsumeToken(hLexDis);
578 Assert(pTokDis);
579
580 pTokCapstone = RTScriptLexConsumeToken(hLexCapstone);
581 Assert(pTokCapstone);
582 } while ( pTokDis->enmType != RTSCRIPTLEXTOKTYPE_EOS
583 || pTokCapstone->enmType != RTSCRIPTLEXTOKTYPE_EOS);
584
585 if (fFailed)
586 RTTestIFailureDetails("%#08RX32: rcDis=%s, capstone=%s %s\n",
587 u32Insn, szOutput, pInstr->mnemonic, pInstr->op_str);
588 }
589
590 RTScriptLexDestroy(hLexCapstone);
591 RTScriptLexDestroy(hLexDis);
592 }
593 else
594 {
595 RTTestIFailureDetails("%#08RX32: Dis=%s, capstone=disassembly failure\n",
596 u32Insn, szOutput);
597 }
598 }
599 }
600
601 /* Cleanup. */
602 cs_close(&hDisasm);
603}
604#endif
605
606int main(int argc, char **argv)
607{
608 RT_NOREF2(argc, argv);
609 RTTEST hTest;
610 RTEXITCODE rcExit = RTTestInitAndCreate("tstDisasm", &hTest);
611 if (rcExit)
612 return rcExit;
613 RTTestBanner(hTest);
614
615 static const struct
616 {
617 const char *pszDesc;
618 uint8_t const *pbStart;
619 uintptr_t uEndPtr;
620 DISCPUMODE enmCpuMode;
621 const unsigned char *pbSrc;
622 unsigned cbSrc;
623 } aSnippets[] =
624 {
625#ifndef RT_OS_OS2
626 { "64-bit", (uint8_t const *)(uintptr_t)TestProcA64, (uintptr_t)&TestProcA64_EndProc, DISCPUMODE_ARMV8_A64,
627 g_abtstDisasmArmv8_1, g_cbtstDisasmArmv8_1 },
628#endif
629 };
630
631 for (unsigned i = 0; i < RT_ELEMENTS(aSnippets); i++)
632 testDisas(aSnippets[i].pszDesc, aSnippets[i].pbStart, aSnippets[i].uEndPtr, aSnippets[i].enmCpuMode,
633 aSnippets[i].pbSrc, aSnippets[i].cbSrc);
634
635#if defined(TST_DISASM_WITH_CAPSTONE_DISASSEMBLER) && !defined(DIS_CORE_ONLY)
636 testDisasComplianceAgaistCapstone();
637#endif
638
639 return RTTestSummaryAndDestroy(hTest);
640}
641
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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