Changeset 106003 in vbox
- Timestamp:
- Sep 10, 2024 11:46:42 AM (8 months ago)
- svn:sync-xref-src-repo-rev:
- 164749
- Location:
- trunk/src/VBox/Disassembler/testcase
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Disassembler/testcase/Makefile.kmk
r105756 r106003 100 100 $(PATH_STAGE_LIB)/DisasmR3$(VBOX_SUFF_LIB) \ 101 101 $(LIB_RUNTIME) 102 103 if defined(TST_DISASM_WITH_CAPSTONE_DISASSEMBLER) 104 tstDisasmArmv8-1_DEFS += TST_DISASM_WITH_CAPSTONE_DISASSEMBLER 105 tstDisasmArmv8-1_LIBS.darwin += /opt/homebrew/lib/libcapstone.dylib 106 tstDisasmArmv8-1_LIBS.linux += capstone 107 endif 108 102 109 endif 103 110 -
trunk/src/VBox/Disassembler/testcase/tstDisasmArmv8-1.cpp
r105858 r106003 32 32 #define VBOX_DIS_WITH_ARMV8 33 33 #include <VBox/dis.h> 34 #include <VBox/err.h> 34 35 #include <iprt/test.h> 35 36 #include <iprt/ctype.h> … … 37 38 #include <iprt/err.h> 38 39 #include <iprt/script.h> 40 #include <iprt/sg.h> 39 41 #include <iprt/stream.h> 40 42 43 #ifdef TST_DISASM_WITH_CAPSTONE_DISASSEMBLER 44 # include "/opt/homebrew/include/capstone/capstone.h" 45 #endif 46 41 47 #include "tstDisasmArmv8-1-tests.h" 42 48 43 49 typedef struct TESTRDR 44 50 { 45 const char *pb;46 unsigned cb;51 RTSGSEG aSegs[3]; 52 RTSGBUF SgBuf; 47 53 } TESTRDR; 48 54 typedef TESTRDR *PTESTRDR; … … 141 147 size_t cchBuf, size_t *pcchRead, void *pvUser) 142 148 { 143 RT_NOREF(hScriptLex );149 RT_NOREF(hScriptLex, offBuf); 144 150 145 151 PTESTRDR pRdr = (PTESTRDR)pvUser; 146 size_t cbCopy = RT_MIN(cchBuf / sizeof(char), pRdr->cb - offBuf); 147 int rc = VINF_SUCCESS; 148 149 *pcchRead = cbCopy * sizeof(char); 150 151 if (cbCopy) 152 memcpy(pchCur, &pRdr->pb[offBuf], cbCopy); 153 else 154 rc = VINF_EOF; 155 156 return rc; 152 size_t cbCopied = RTSgBufCopyToBuf(&pRdr->SgBuf, pchCur, cchBuf * sizeof(char)); 153 154 *pcchRead = cbCopied * sizeof(char); 155 if (!cbCopied) 156 return VINF_EOF; 157 158 return VINF_SUCCESS; 157 159 } 158 160 … … 166 168 TESTRDR Rdr; 167 169 168 Rdr.pb = (const char *)pbSrc; 169 Rdr.cb = cbSrc; 170 Rdr.aSegs[0].pvSeg = (void *)pbSrc; 171 Rdr.aSegs[0].cbSeg = cbSrc; 172 RTSgBufInit(&Rdr.SgBuf, &Rdr.aSegs[0], 1); 170 173 int rc = RTScriptLexCreateFromReader(&hLexSource, testDisasmLexerRead, 171 174 NULL /*pfnDtor*/, &Rdr /*pvUser*/, cbSrc, … … 410 413 411 414 415 #if defined(TST_DISASM_WITH_CAPSTONE_DISASSEMBLER) && !defined(DIS_CORE_ONLY) 416 /** 417 * Testcase generating all possible 32-bit instruction values and checking our disassembler 418 * for compliance against the capstone disassembler (based on LLVM). 419 */ 420 static void testDisasComplianceAgaistCapstone(void) 421 { 422 /** @todo SMP */ 423 424 csh hDisasm = ~(size_t)0; 425 cs_err rcCs = cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &hDisasm); 426 AssertMsgReturnVoid(rcCs == CS_ERR_OK, ("%d (%#x)\n", rcCs, rcCs)); 427 428 char szOutput[256] = {0}; 429 430 for (uint32_t u32Insn = 0; u32Insn < UINT32_MAX; u32Insn++) 431 { 432 cs_insn *pInstr; 433 size_t cInstrs = cs_disasm(hDisasm, (const uint8_t *)&u32Insn, sizeof(u32Insn), 434 (uintptr_t)&u32Insn, 1, &pInstr); 435 436 DISSTATE Dis; 437 uint32_t cb = 1; 438 439 /* 440 * Can't use DISInstrToStr() here as it would add addresses and opcode bytes 441 * which would trip the semantic matching later on. 442 */ 443 int rc = DISInstrEx((uintptr_t)&u32Insn, DISCPUMODE_ARMV8_A64, DISOPTYPE_ALL, 444 NULL /*pfnReadBytes*/, NULL /*pvUser*/, &Dis, &cb); 445 if (rc == VERR_DIS_INVALID_OPCODE) 446 { 447 /* Check whether capstone could successfully disassembler the instruction. */ 448 if (cInstrs) 449 { 450 RTTestIFailureDetails("%#08RX32: rcDis==VERR_DIS_INVALID_OPCODE, capstone=%s %s\n", 451 u32Insn, pInstr->mnemonic, pInstr->op_str); 452 } 453 /* else: Invalid encoding from both disassemblers, continue. */ 454 } 455 else 456 { 457 RTTESTI_CHECK_RC(rc, VINF_SUCCESS); 458 RTTESTI_CHECK(cb == Dis.cbInstr); 459 RTTESTI_CHECK(cb == sizeof(uint32_t)); 460 461 size_t cch = DISFormatArmV8Ex(&Dis, &szOutput[0], sizeof(szOutput), 462 DIS_FMT_FLAGS_RELATIVE_BRANCH, 463 NULL /*pfnGetSymbol*/, NULL /*pvUser*/); 464 Assert(cch); 465 466 szOutput[cch] = '\0'; 467 RTStrStripR(szOutput); 468 RTTESTI_CHECK(szOutput[0]); 469 470 if (cInstrs > 0) 471 { 472 /* Compare semantically. */ 473 474 RTSCRIPTLEX hLexCapstone = NULL; 475 TESTRDR Rdr; 476 477 Rdr.aSegs[0].pvSeg = pInstr->mnemonic; 478 Rdr.aSegs[0].cbSeg = strlen(pInstr->mnemonic); 479 Rdr.aSegs[1].pvSeg = (void *)" "; 480 Rdr.aSegs[1].cbSeg = 1; 481 Rdr.aSegs[2].pvSeg = pInstr->op_str; 482 Rdr.aSegs[2].cbSeg = strlen(pInstr->op_str); 483 RTSgBufInit(&Rdr.SgBuf, &Rdr.aSegs[0], 3); 484 rc = RTScriptLexCreateFromReader(&hLexCapstone, testDisasmLexerRead, 485 NULL /*pfnDtor*/, &Rdr /*pvUser*/, 0 /*cchBuf*/, 486 NULL /*phStrCacheId*/, NULL /*phStrCacheStringLit*/, 487 &s_LexCfg); 488 RTTESTI_CHECK_RC(rc, VINF_SUCCESS); 489 490 /* Build the lexer and compare that it semantically is equal to the source input. */ 491 RTSCRIPTLEX hLexDis = NULL; 492 rc = RTScriptLexCreateFromString(&hLexDis, szOutput, NULL /*phStrCacheId*/, 493 NULL /*phStrCacheStringLit*/, &s_LexCfg); 494 RTTESTI_CHECK_RC(rc, VINF_SUCCESS); 495 if (RT_SUCCESS(rc)) 496 { 497 PCRTSCRIPTLEXTOKEN pTokDis; 498 rc = RTScriptLexQueryToken(hLexDis, &pTokDis); 499 RTTESTI_CHECK_RC(rc, VINF_SUCCESS); 500 501 PCRTSCRIPTLEXTOKEN pTokCapstone; 502 rc = RTScriptLexQueryToken(hLexCapstone, &pTokCapstone); 503 RTTESTI_CHECK_RC(rc, VINF_SUCCESS); 504 505 /* Now compare the token streams until we hit EOS in the disassembly lexer. */ 506 bool fFailed = false; 507 do 508 { 509 if (pTokCapstone->enmType == pTokDis->enmType) 510 { 511 switch (pTokCapstone->enmType) 512 { 513 case RTSCRIPTLEXTOKTYPE_IDENTIFIER: 514 { 515 int iCmp = strcmp(pTokCapstone->Type.Id.pszIde, pTokDis->Type.Id.pszIde); 516 if (iCmp) 517 fFailed = true; 518 break; 519 } 520 case RTSCRIPTLEXTOKTYPE_NUMBER: 521 if (pTokCapstone->Type.Number.enmType == pTokDis->Type.Number.enmType) 522 { 523 switch (pTokCapstone->Type.Number.enmType) 524 { 525 case RTSCRIPTLEXTOKNUMTYPE_NATURAL: 526 { 527 if (pTokCapstone->Type.Number.Type.u64 != pTokDis->Type.Number.Type.u64) 528 fFailed = true; 529 break; 530 } 531 case RTSCRIPTLEXTOKNUMTYPE_INTEGER: 532 { 533 if (pTokCapstone->Type.Number.Type.i64 != pTokDis->Type.Number.Type.i64) 534 fFailed = true; 535 break; 536 } 537 case RTSCRIPTLEXTOKNUMTYPE_REAL: 538 default: 539 AssertReleaseFailed(); 540 } 541 } 542 else 543 fFailed = true; 544 break; 545 case RTSCRIPTLEXTOKTYPE_PUNCTUATOR: 546 { 547 int iCmp = strcmp(pTokCapstone->Type.Punctuator.pPunctuator->pszMatch, 548 pTokDis->Type.Punctuator.pPunctuator->pszMatch); 549 if (iCmp) 550 fFailed = true; 551 break; 552 } 553 554 /* These should never occur and indicate an issue in the lexer. */ 555 case RTSCRIPTLEXTOKTYPE_KEYWORD: 556 case RTSCRIPTLEXTOKTYPE_STRINGLIT: 557 case RTSCRIPTLEXTOKTYPE_OPERATOR: 558 case RTSCRIPTLEXTOKTYPE_INVALID: 559 case RTSCRIPTLEXTOKTYPE_ERROR: 560 case RTSCRIPTLEXTOKTYPE_EOS: 561 fFailed = true; 562 break; 563 default: 564 AssertFailed(); 565 } 566 } 567 else 568 fFailed = true; 569 570 /* Abort on error. */ 571 if (fFailed) 572 break; 573 574 /* Advance to the next token. */ 575 pTokDis = RTScriptLexConsumeToken(hLexDis); 576 Assert(pTokDis); 577 578 pTokCapstone = RTScriptLexConsumeToken(hLexCapstone); 579 Assert(pTokCapstone); 580 } while ( pTokDis->enmType != RTSCRIPTLEXTOKTYPE_EOS 581 || pTokCapstone->enmType != RTSCRIPTLEXTOKTYPE_EOS); 582 583 if (fFailed) 584 RTTestIFailureDetails("%#08RX32: rcDis=%s, capstone=%s %s\n", 585 u32Insn, szOutput, pInstr->mnemonic, pInstr->op_str); 586 } 587 588 RTScriptLexDestroy(hLexCapstone); 589 RTScriptLexDestroy(hLexDis); 590 } 591 else 592 { 593 RTTestIFailureDetails("%#08RX32: Dis=%s, capstone=disassembly failure\n", 594 u32Insn, szOutput); 595 } 596 } 597 } 598 599 /* Cleanup. */ 600 cs_close(&hDisasm); 601 } 602 #endif 603 412 604 int main(int argc, char **argv) 413 605 { … … 439 631 aSnippets[i].pbSrc, aSnippets[i].cbSrc); 440 632 633 #if defined(TST_DISASM_WITH_CAPSTONE_DISASSEMBLER) && !defined(DIS_CORE_ONLY) 634 testDisasComplianceAgaistCapstone(); 635 #endif 636 441 637 return RTTestSummaryAndDestroy(hTest); 442 638 }
Note:
See TracChangeset
for help on using the changeset viewer.