VirtualBox

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

Last change on this file since 107044 was 106805, checked in by vboxsync, 4 weeks ago

Disassembler: Decode RCW compare and swap and RCW compare and swap pair instructions, bugref:10394

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

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