Changeset 41658 in vbox
- Timestamp:
- Jun 11, 2012 10:21:44 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 78464
- Location:
- trunk
- Files:
-
- 31 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/dis.h
r41501 r41658 4 4 5 5 /* 6 * Copyright (C) 2006-20 07Oracle Corporation6 * Copyright (C) 2006-2012 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 370 370 typedef struct OP_PARAMETER 371 371 { 372 /** @todo switch param and parval and move disp64 and flags up here with the other 64-bit vars to get more natural alignment and save space. */373 int param;374 372 uint64_t parval; 375 #ifndef DIS_SEPARATE_FORMATTER 376 char szParam[32];377 #endif 378 379 int32_t disp8 , disp16, disp32;373 uint64_t flags; 374 int64_t disp64; 375 int32_t disp32; 376 int32_t disp16; 377 int32_t disp8; 380 378 uint32_t size; 381 382 int64_t disp64; 383 uint64_t flags; 379 int32_t param; 384 380 385 381 union … … 409 405 uint32_t scale; 410 406 407 #ifndef DIS_SEPARATE_FORMATTER 408 char szParam[32]; 409 #endif 411 410 } OP_PARAMETER; 412 411 /** Pointer to opcode parameter. */ … … 421 420 typedef const struct OPCODE *PCOPCODE; 422 421 423 typedef DECLCALLBACK(int) FN_DIS_READBYTES(RTUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata); 424 typedef FN_DIS_READBYTES *PFN_DIS_READBYTES; 422 /** 423 * Callback for reading opcode bytes. 424 * 425 * @param pDisState Pointer to the CPU state. The primary user argument 426 * can be retrived from DISCPUSTATE::apvUserData[0]. If 427 * more is required these can be passed in the 428 * subsequent slots. 429 * @param pbDst Pointer to output buffer. 430 * @param uSrcAddr The address to start reading at. 431 * @param cbToRead The number of bytes to read. 432 */ 433 typedef DECLCALLBACK(int) FNDISREADBYTES(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead); 434 /** Pointer to a opcode byte reader. */ 435 typedef FNDISREADBYTES *PFNDISREADBYTES; 425 436 426 437 /** Parser callback. … … 431 442 typedef struct DISCPUSTATE 432 443 { 433 /* Global setting*/444 /** Global setting. */ 434 445 DISCPUMODE mode; 435 446 436 /* Per instruction prefix settings*/447 /** Per instruction prefix settings. */ 437 448 uint32_t prefix; 438 449 /** segment prefix value. */ … … 452 463 union 453 464 { 454 /* Bitfield view */465 /** Bitfield view */ 455 466 struct 456 467 { … … 459 470 unsigned Mod : 2; 460 471 } Bits; 461 /* unsigned view */472 /** unsigned view */ 462 473 unsigned u; 463 474 } ModRM; … … 466 477 union 467 478 { 468 /* Bitfield view */479 /** Bitfield view */ 469 480 struct 470 481 { … … 473 484 unsigned Scale : 2; 474 485 } Bits; 475 /* unsigned view */486 /** unsigned view */ 476 487 unsigned u; 477 488 } SIB; 478 479 int32_t disp; 489 int32_t i32SibDisp; 490 491 /** The instruction size. */ 492 uint32_t opsize; 493 /** The address of the instruction. */ 494 RTUINTPTR uInstrAddr; 495 /** The offsetted address of the instruction. */ 496 RTUINTPTR opaddr; 497 /** The size of the prefix bytes. */ 498 uint8_t cbPrefix; 480 499 481 500 /** First opcode byte of instruction. */ 482 501 uint8_t opcode; 483 /** Last prefix byte (for SSE2 extension tables) */502 /** Last prefix byte (for SSE2 extension tables). */ 484 503 uint8_t lastprefix; 485 RTUINTPTR opaddr; 486 uint32_t opsize; 504 /** The instruction bytes. */ 505 uint8_t abInstr[16]; 506 507 /** Internal: pointer to disassembly function table */ 508 PFNDISPARSE *pfnDisasmFnTable; 509 /** Internal: instruction filter */ 510 uint32_t uFilter; 511 /** Return code set by a worker function like the opcode bytes readers. */ 512 int32_t rc; 513 514 /** Pointer to the current instruction. */ 515 PCOPCODE pCurInstr; 487 516 #ifndef DIS_CORE_ONLY 488 517 /** Opcode format string for current instruction. */ … … 490 519 #endif 491 520 492 /** Internal: pointer to disassembly function table */ 493 PFNDISPARSE *pfnDisasmFnTable; 494 /** Internal: instruction filter */ 495 uint32_t uFilter; 496 497 /** Pointer to the current instruction. */ 498 PCOPCODE pCurInstr; 499 521 /** Optional read function */ 522 PFNDISREADBYTES pfnReadBytes; 523 /** User data slots for the read callback. The first entry is used for the 524 * pvUser argument, the rest are up for grabs. 525 * @remarks This must come last so that we can memset everything before this. */ 500 526 void *apvUserData[3]; 501 502 /** Optional read function */503 PFN_DIS_READBYTES pfnReadBytes;504 #ifdef __L4ENV__505 jmp_buf *pJumpBuffer;506 #endif /* __L4ENV__ */507 527 } DISCPUSTATE; 508 528 … … 531 551 532 552 533 /** 534 * Disassembles a code block. 535 * 536 * @returns VBox error code 537 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode 538 * set correctly. 539 * @param pvCodeBlock Pointer to the structure to disassemble. 540 * @param cbMax Maximum number of bytes to disassemble. 541 * @param pcbSize Where to store the size of the instruction. 542 * NULL is allowed. 543 * 544 * 545 * @todo Define output callback. 546 * @todo Using signed integers as sizes is a bit odd. There are still 547 * some GCC warnings about mixing signed and unsigned integers. 548 * @todo Need to extend this interface to include a code address so we 549 * can disassemble GC code. Perhaps a new function is better... 550 * @remark cbMax isn't respected as a boundary. DISInstr() will read beyond cbMax. 551 * This means *pcbSize >= cbMax sometimes. 552 */ 553 DISDECL(int) DISBlock(PDISCPUSTATE pCpu, RTUINTPTR pvCodeBlock, unsigned cbMax, unsigned *pSize); 554 555 /** 556 * Disassembles one instruction 557 * 558 * @returns VBox error code 559 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode 560 * set correctly. 561 * @param pu8Instruction Pointer to the instrunction to disassemble. 562 * @param u32EipOffset Offset to add to instruction address to get the real virtual address 563 * @param pcbSize Where to store the size of the instruction. 564 * NULL is allowed. 565 * @param pszOutput Storage for disassembled instruction 566 * 567 * @todo Define output callback. 568 */ 569 DISDECL(int) DISInstr(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize, char *pszOutput); 570 571 /** 572 * Disassembles one instruction 573 * 574 * @returns VBox error code 575 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode 576 * set correctly. 577 * @param pu8Instruction Pointer to the structure to disassemble. 578 * @param u32EipOffset Offset to add to instruction address to get the real virtual address 579 * @param pcbSize Where to store the size of the instruction. 580 * NULL is allowed. 581 * @param pszOutput Storage for disassembled instruction 582 * @param uFilter Instruction type filter 583 * 584 * @todo Define output callback. 585 */ 586 DISDECL(int) DISInstrEx(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, uint32_t u32EipOffset, uint32_t *pcbSize, 587 char *pszOutput, unsigned uFilter); 588 589 /** 590 * Parses one instruction. 591 * The result is found in pCpu. 592 * 593 * @returns VBox error code 594 * @param pCpu Pointer to cpu structure which has DISCPUSTATE::mode set correctly. 595 * @param InstructionAddr Pointer to the instruction to parse. 596 * @param pcbInstruction Where to store the size of the instruction. 597 * NULL is allowed. 598 */ 599 DISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction); 600 601 /** 602 * Parses one guest instruction. 603 * The result is found in pCpu and pcbInstruction. 604 * 605 * @returns VBox status code. 606 * @param InstructionAddr Address of the instruction to decode. What this means 607 * is left to the pfnReadBytes function. 608 * @param enmCpuMode The CPU mode. CPUMODE_32BIT, CPUMODE_16BIT, or CPUMODE_64BIT. 609 * @param pfnReadBytes Callback for reading instruction bytes. 610 * @param pvUser User argument for the instruction reader. (Ends up in apvUserData[0].) 611 * @param pCpu Pointer to cpu structure. Will be initialized. 612 * @param pcbInstruction Where to store the size of the instruction. 613 * NULL is allowed. 614 */ 615 DISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, DISCPUMODE enmCpuMode, PFN_DIS_READBYTES pfnReadBytes, void *pvUser, 616 PDISCPUSTATE pCpu, unsigned *pcbInstruction); 553 DISDECL(int) DISInstr(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput); 554 DISDECL(int) DISInstrWithOff(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, RTUINTPTR offRealAddr, uint32_t *pcbSize, char *pszOutput); 555 DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser, 556 PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput); 557 DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, RTUINTPTR offRealAddr, DISCPUMODE enmCpuMode, 558 PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter, 559 PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput); 560 561 DISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, uint32_t *pcbInstruction); 562 DISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser, 563 PDISCPUSTATE pCpu, uint32_t *pcbInstruction); 617 564 618 565 DISDECL(int) DISGetParamSize(PDISCPUSTATE pCpu, POP_PARAMETER pParam); … … 620 567 DISDECL(uint8_t) DISQuerySegPrefixByte(PDISCPUSTATE pCpu); 621 568 622 /**623 * Returns the value of the parameter in pParam624 *625 * @returns VBox error code626 * @param pCtx Exception structure pointer627 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode628 * set correctly.629 * @param pParam Pointer to the parameter to parse630 * @param pParamVal Pointer to parameter value (OUT)631 * @param parmtype Parameter type632 *633 * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!!634 *635 */636 569 DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, POP_PARAMVAL pParamVal, PARAM_TYPE parmtype); 637 570 DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PDISCPUSTATE pCpu, POP_PARAMETER pParam, void **ppReg, size_t *pcbSize); -
trunk/include/VBox/err.h
r41573 r41658 1932 1932 /** Generic failure during disassembly. */ 1933 1933 #define VERR_DIS_GEN_FAILURE (-4201) 1934 /** No read callback. */ 1935 #define VERR_DIS_NO_READ_CALLBACK (-4202) 1936 /** Invalid Mod/RM. */ 1937 #define VERR_DIS_INVALID_MODRM (-4203) 1938 /** Invalid parameter index. */ 1939 #define VERR_DIS_INVALID_PARAMETER (-4204) 1940 /** Reading opcode bytes failed. */ 1941 #define VERR_DIS_MEM_READ (-4205) 1934 1942 /** @} */ 1935 1943 -
trunk/include/VBox/vmm/iem.h
r40453 r41658 41 41 VMMDECL(VBOXSTRICTRC) IEMExecOne(PVMCPU pVCpu); 42 42 VMMDECL(VBOXSTRICTRC) IEMExecOneEx(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint32_t *pcbWritten); 43 VMMDECL(VBOXSTRICTRC) IEMExecOneWithOpcodes(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, 44 RTGCPTR GCPtrOpcodeBytes, const void *pvOpcodeBytes, size_t cbOpcodeBytes); 43 45 VMMDECL(VBOXSTRICTRC) IEMExecLots(PVMCPU pVCpu); 44 46 VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2); -
trunk/include/VBox/vmm/patm.h
r40453 r41658 238 238 * @param pCtxCore The relevant core context. 239 239 */ 240 VMM DECL(int) PATMHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame);240 VMMRCDECL(int) PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame); 241 241 242 242 /** -
trunk/src/VBox/Devices/PC/BIOS-new/MakeDebianBiosAssembly.cpp
r41609 r41658 904 904 905 905 /** 906 * Disassembler callback for reading opcode bytes. 907 * 908 * @returns VINF_SUCCESS. 909 * @param uFlatAddr The address to read at. 910 * @param pbDst Where to store them. 911 * @param cbToRead How many to read. 912 * @param pvUser Unused. 913 */ 914 static DECLCALLBACK(int) disReadOpcodeBytes(RTUINTPTR uFlatAddr, uint8_t *pbDst, unsigned cbToRead, void *pvUser) 915 { 916 if (uFlatAddr + cbToRead >= VBOX_BIOS_BASE + _64K) 906 * @callback_method_impl{FNDISREADBYTES} 907 * 908 * @remarks @a uSrcAddr is the flat address. 909 */ 910 static DECLCALLBACK(int) disReadOpcodeBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead) 911 { 912 if (uSrcAddr + cbToRead >= VBOX_BIOS_BASE + _64K) 917 913 { 918 914 RT_BZERO(pbDst, cbToRead); 919 if (u FlatAddr >= VBOX_BIOS_BASE + _64K)915 if (uSrcAddr >= VBOX_BIOS_BASE + _64K) 920 916 cbToRead = 0; 921 917 else 922 cbToRead = VBOX_BIOS_BASE + _64K - u FlatAddr;923 } 924 memcpy(pbDst, &g_pbImg[u FlatAddr - VBOX_BIOS_BASE], cbToRead);925 NOREF(p vUser);918 cbToRead = VBOX_BIOS_BASE + _64K - uSrcAddr; 919 } 920 memcpy(pbDst, &g_pbImg[uSrcAddr - VBOX_BIOS_BASE], cbToRead); 921 NOREF(pDisState); 926 922 return VINF_SUCCESS; 927 923 } -
trunk/src/VBox/Disassembler/Disasm.cpp
r33540 r41658 34 34 35 35 /** 36 * Disassembles a code block.36 * Disassembles one instruction 37 37 * 38 38 * @returns VBox error code 39 39 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode 40 40 * set correctly. 41 * @param pvCodeBlock Pointer to the structure to disassemble. 42 * @param cbMax Maximum number of bytes to disassemble. 41 * @param uInstrAddr Pointer to the structure to disassemble. 43 42 * @param pcbSize Where to store the size of the instruction. 44 43 * NULL is allowed. 45 * 44 * @param pszOutput Storage for disassembled instruction 46 45 * 47 46 * @todo Define output callback. 48 * @todo Using signed integers as sizes is a bit odd. There are still 49 * some GCC warnings about mixing signed and unsigned integers. 50 * @todo Need to extend this interface to include a code address so we 51 * can disassemble GC code. Perhaps a new function is better... 52 * @remark cbMax isn't respected as a boundary. DISInstr() will read beyond cbMax. 53 * This means *pcbSize >= cbMax sometimes. 54 */ 55 DISDECL(int) DISBlock(PDISCPUSTATE pCpu, RTUINTPTR pvCodeBlock, unsigned cbMax, unsigned *pSize) 56 { 57 unsigned i = 0; 58 char szOutput[256]; 59 60 while (i < cbMax) 61 { 62 unsigned cbInstr; 63 int rc = DISInstr(pCpu, pvCodeBlock + i, 0, &cbInstr, szOutput); 64 if (RT_FAILURE(rc)) 65 return rc; 66 67 i += cbInstr; 68 } 69 70 if (pSize) 71 *pSize = i; 72 return true; 47 */ 48 DISDECL(int) DISInstr(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput) 49 { 50 return DISInstrEx(uInstrAddr, 0, enmCpuMode, NULL, NULL, OPTYPE_ALL, 51 pCpu, pcbSize, pszOutput); 73 52 } 74 53 … … 79 58 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode 80 59 * set correctly. 81 * @param pu8Instruction Pointer to the structure to disassemble. 82 * @param u32EipOffset Offset to add to instruction address to get the real virtual address 60 * @param uInstrAddr Pointer to the structure to disassemble. 61 * @param offRealAddr Offset to add to instruction address to get the real 62 * virtual address. 83 63 * @param pcbSize Where to store the size of the instruction. 84 64 * NULL is allowed. … … 87 67 * @todo Define output callback. 88 68 */ 89 DISDECL(int) DISInstr(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize, 90 char *pszOutput) 91 { 92 return DISInstrEx(pCpu, pu8Instruction, u32EipOffset, pcbSize, pszOutput, OPTYPE_ALL); 69 DISDECL(int) DISInstrWithOff(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, RTUINTPTR offRealAddr, 70 unsigned *pcbSize, char *pszOutput) 71 { 72 return DISInstrEx(uInstrAddr, offRealAddr, pCpu->mode, pCpu->pfnReadBytes, pCpu->apvUserData[0], OPTYPE_ALL, 73 pCpu, pcbSize, pszOutput); 74 } 75 76 /** 77 * Disassembles one instruction with a byte fetcher caller. 78 * 79 * @returns VBox error code 80 * @param uInstrAddr Pointer to the structure to disassemble. 81 * @param enmCpuMode The CPU mode. 82 * @param pfnCallback The byte fetcher callback. 83 * @param pvUser The user argument (found in 84 * DISCPUSTATE::apvUserData[0]). 85 * @param pCpu Where to return the disassembled instruction. 86 * @param pcbSize Where to store the size of the instruction. 87 * NULL is allowed. 88 * @param pszOutput Storage for disassembled instruction 89 * 90 * @todo Define output callback. 91 */ 92 DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser, 93 PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput) 94 95 { 96 return DISInstrEx(uInstrAddr, 0, enmCpuMode, pfnReadBytes, pvUser, OPTYPE_ALL, 97 pCpu, pcbSize, pszOutput); 93 98 } 94 99 … … 99 104 * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode 100 105 * set correctly. 101 * @param pu8InstructionPointer to the structure to disassemble.106 * @param uInstrAddr Pointer to the structure to disassemble. 102 107 * @param u32EipOffset Offset to add to instruction address to get the real virtual address 103 108 * @param pcbSize Where to store the size of the instruction. … … 108 113 * @todo Define output callback. 109 114 */ 110 DISDECL(int) DISInstrEx(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize, 111 char *pszOutput, unsigned uFilter) 112 { 113 unsigned i = 0, prefixbytes; 114 unsigned idx, inc; 115 const OPCODE *paOneByteMap; 116 #ifdef __L4ENV__ 117 jmp_buf jumpbuffer; 118 #endif 119 120 //reset instruction settings 121 pCpu->prefix = PREFIX_NONE; 122 pCpu->enmPrefixSeg = DIS_SELREG_DS; 123 pCpu->ModRM.u = 0; 124 pCpu->SIB.u = 0; 125 pCpu->lastprefix = 0; 126 pCpu->param1.parval = 0; 127 pCpu->param2.parval = 0; 128 pCpu->param3.parval = 0; 129 pCpu->param1.szParam[0] = 0; 130 pCpu->param2.szParam[0] = 0; 131 pCpu->param3.szParam[0] = 0; 132 pCpu->param1.size = 0; 133 pCpu->param2.size = 0; 134 pCpu->param3.size = 0; 135 pCpu->param1.flags = 0; 136 pCpu->param2.flags = 0; 137 pCpu->param3.flags = 0; 138 pCpu->uFilter = uFilter; 139 pCpu->pfnDisasmFnTable = pfnFullDisasm; 140 141 if (pszOutput) 142 *pszOutput = '\0'; 143 144 if (pCpu->mode == CPUMODE_64BIT) 115 DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, RTUINTPTR offRealAddr, DISCPUMODE enmCpuMode, 116 PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter, 117 PDISCPUSTATE pCpu, uint32_t *pcbSize, char *pszOutput) 118 { 119 const OPCODE *paOneByteMap; 120 121 /* 122 * Initialize the CPU state. 123 * Note! The RT_BZERO make ASSUMPTIONS about the placement of apvUserData. 124 */ 125 RT_BZERO(pCpu, RT_OFFSETOF(DISCPUSTATE, apvUserData)); 126 127 pCpu->mode = enmCpuMode; 128 if (enmCpuMode == CPUMODE_64BIT) 145 129 { 146 paOneByteMap = g_aOneByteMapX64;147 pCpu->addrmode = CPUMODE_64BIT;148 pCpu->opmode = CPUMODE_32BIT;130 paOneByteMap = g_aOneByteMapX64; 131 pCpu->addrmode = CPUMODE_64BIT; 132 pCpu->opmode = CPUMODE_32BIT; 149 133 } 150 134 else 151 135 { 152 paOneByteMap = g_aOneByteMapX86;153 pCpu->addrmode = pCpu->mode;154 pCpu->opmode = pCpu->mode;136 paOneByteMap = g_aOneByteMapX86; 137 pCpu->addrmode = enmCpuMode; 138 pCpu->opmode = enmCpuMode; 155 139 } 156 157 prefixbytes = 0; 158 #ifndef __L4ENV__ /* Unfortunately, we have no exception handling in l4env */ 159 try 160 #else 161 pCpu->pJumpBuffer = &jumpbuffer; 162 if (setjmp(jumpbuffer) == 0) 163 #endif 140 pCpu->prefix = PREFIX_NONE; 141 pCpu->enmPrefixSeg = DIS_SELREG_DS; 142 pCpu->uInstrAddr = uInstrAddr; 143 pCpu->opaddr = uInstrAddr + offRealAddr; 144 pCpu->pfnDisasmFnTable = pfnFullDisasm; 145 pCpu->uFilter = uFilter; 146 pCpu->rc = VINF_SUCCESS; 147 pCpu->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault; 148 pCpu->apvUserData[0] = pvUser; 149 150 /* 151 * Parse the instruction byte by byte. 152 */ 153 unsigned i = 0; 154 unsigned cbPrefix = 0; /** @todo this isn't really needed, is it? Seems to be a bit too many variables tracking the same stuff here. cbInc, i, cbPrefix, idx... */ 155 for (;;) 164 156 { 165 while(1) 157 uint8_t codebyte = DISReadByte(pCpu, uInstrAddr+i); 158 uint8_t opcode = paOneByteMap[codebyte].opcode; 159 160 /* Hardcoded assumption about OP_* values!! */ 161 if (opcode <= OP_LAST_PREFIX) 166 162 { 167 uint8_t codebyte = DISReadByte(pCpu, pu8Instruction+i); 168 uint8_t opcode = paOneByteMap[codebyte].opcode; 169 170 /* Hardcoded assumption about OP_* values!! */ 171 if (opcode <= OP_LAST_PREFIX) 163 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */ 164 if (opcode != OP_REX) 172 165 { 173 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */ 174 if (opcode != OP_REX) 175 { 176 pCpu->lastprefix = opcode; 177 pCpu->prefix &= ~PREFIX_REX; 178 } 179 180 switch(opcode) 181 { 182 case OP_INVALID: 183 #if 0 //defined (DEBUG_Sander) 184 AssertMsgFailed(("Invalid opcode!!\n")); 185 #endif 186 return VERR_DIS_INVALID_OPCODE; 187 188 // segment override prefix byte 189 case OP_SEG: 190 pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START); 191 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */ 192 if ( pCpu->mode != CPUMODE_64BIT 193 || pCpu->enmPrefixSeg >= DIS_SELREG_FS) 194 { 195 pCpu->prefix |= PREFIX_SEG; 196 } 197 i += sizeof(uint8_t); 198 prefixbytes++; 199 continue; //fetch the next byte 200 201 // lock prefix byte 202 case OP_LOCK: 203 pCpu->prefix |= PREFIX_LOCK; 204 i += sizeof(uint8_t); 205 prefixbytes++; 206 continue; //fetch the next byte 207 208 // address size override prefix byte 209 case OP_ADDRSIZE: 210 pCpu->prefix |= PREFIX_ADDRSIZE; 211 if (pCpu->mode == CPUMODE_16BIT) 212 pCpu->addrmode = CPUMODE_32BIT; 213 else 214 if (pCpu->mode == CPUMODE_32BIT) 215 pCpu->addrmode = CPUMODE_16BIT; 216 else 217 pCpu->addrmode = CPUMODE_32BIT; /* 64 bits */ 218 219 i += sizeof(uint8_t); 220 prefixbytes++; 221 continue; //fetch the next byte 222 223 // operand size override prefix byte 224 case OP_OPSIZE: 225 pCpu->prefix |= PREFIX_OPSIZE; 226 if (pCpu->mode == CPUMODE_16BIT) 227 pCpu->opmode = CPUMODE_32BIT; 228 else 229 pCpu->opmode = CPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */ 230 231 i += sizeof(uint8_t); 232 prefixbytes++; 233 continue; //fetch the next byte 234 235 // rep and repne are not really prefixes, but we'll treat them as such 236 case OP_REPE: 237 pCpu->prefix |= PREFIX_REP; 238 i += sizeof(uint8_t); 239 prefixbytes += sizeof(uint8_t); 240 continue; //fetch the next byte 241 242 case OP_REPNE: 243 pCpu->prefix |= PREFIX_REPNE; 244 i += sizeof(uint8_t); 245 prefixbytes += sizeof(uint8_t); 246 continue; //fetch the next byte 247 248 case OP_REX: 249 Assert(pCpu->mode == CPUMODE_64BIT); 250 /* REX prefix byte */ 251 pCpu->prefix |= PREFIX_REX; 252 pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1); 253 i += sizeof(uint8_t); 254 prefixbytes += sizeof(uint8_t); 255 256 if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W) 257 pCpu->opmode = CPUMODE_64BIT; /* overrides size prefix byte */ 258 continue; //fetch the next byte 259 } 166 pCpu->lastprefix = opcode; 167 pCpu->prefix &= ~PREFIX_REX; 260 168 } 261 169 262 idx = i; 263 i += sizeof(uint8_t); //first opcode byte 264 265 pCpu->opcode = codebyte; 266 /* Prefix byte(s) is/are part of the instruction. */ 267 pCpu->opaddr = pu8Instruction + idx + u32EipOffset - prefixbytes; 268 269 inc = ParseInstruction(pu8Instruction + i, &paOneByteMap[pCpu->opcode], pCpu); 270 271 pCpu->opsize = prefixbytes + inc + sizeof(uint8_t); 272 273 if(pszOutput) { 274 disasmSprintf(pszOutput, pu8Instruction+i-1-prefixbytes, pCpu, &pCpu->param1, &pCpu->param2, &pCpu->param3); 170 switch (opcode) 171 { 172 case OP_INVALID: 173 if (pcbSize) 174 *pcbSize = pCpu->opsize; 175 return pCpu->rc = VERR_DIS_INVALID_OPCODE; 176 177 // segment override prefix byte 178 case OP_SEG: 179 pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START); 180 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */ 181 if ( pCpu->mode != CPUMODE_64BIT 182 || pCpu->enmPrefixSeg >= DIS_SELREG_FS) 183 pCpu->prefix |= PREFIX_SEG; 184 i += sizeof(uint8_t); 185 cbPrefix++; 186 continue; //fetch the next byte 187 188 // lock prefix byte 189 case OP_LOCK: 190 pCpu->prefix |= PREFIX_LOCK; 191 i += sizeof(uint8_t); 192 cbPrefix++; 193 continue; //fetch the next byte 194 195 // address size override prefix byte 196 case OP_ADDRSIZE: 197 pCpu->prefix |= PREFIX_ADDRSIZE; 198 if (pCpu->mode == CPUMODE_16BIT) 199 pCpu->addrmode = CPUMODE_32BIT; 200 else 201 if (pCpu->mode == CPUMODE_32BIT) 202 pCpu->addrmode = CPUMODE_16BIT; 203 else 204 pCpu->addrmode = CPUMODE_32BIT; /* 64 bits */ 205 206 i += sizeof(uint8_t); 207 cbPrefix++; 208 continue; //fetch the next byte 209 210 // operand size override prefix byte 211 case OP_OPSIZE: 212 pCpu->prefix |= PREFIX_OPSIZE; 213 if (pCpu->mode == CPUMODE_16BIT) 214 pCpu->opmode = CPUMODE_32BIT; 215 else 216 pCpu->opmode = CPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */ 217 218 i += sizeof(uint8_t); 219 cbPrefix++; 220 continue; //fetch the next byte 221 222 // rep and repne are not really prefixes, but we'll treat them as such 223 case OP_REPE: 224 pCpu->prefix |= PREFIX_REP; 225 i += sizeof(uint8_t); 226 cbPrefix += sizeof(uint8_t); 227 continue; //fetch the next byte 228 229 case OP_REPNE: 230 pCpu->prefix |= PREFIX_REPNE; 231 i += sizeof(uint8_t); 232 cbPrefix += sizeof(uint8_t); 233 continue; //fetch the next byte 234 235 case OP_REX: 236 Assert(pCpu->mode == CPUMODE_64BIT); 237 /* REX prefix byte */ 238 pCpu->prefix |= PREFIX_REX; 239 pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1); 240 i += sizeof(uint8_t); 241 cbPrefix += sizeof(uint8_t); 242 243 if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W) 244 pCpu->opmode = CPUMODE_64BIT; /* overrides size prefix byte */ 245 continue; //fetch the next byte 275 246 } 276 277 i += inc;278 prefixbytes = 0;279 break;280 247 } 281 } 282 #ifndef __L4ENV__ 283 catch(...) 284 #else 285 else /* setjmp has returned a non-zero value: an exception occurred */ 286 #endif 287 { 288 if (pcbSize) 289 *pcbSize = 0; 290 return VERR_DIS_GEN_FAILURE; 248 249 pCpu->cbPrefix = i; Assert(cbPrefix == i); 250 pCpu->opcode = codebyte; 251 252 unsigned idx = i; 253 i += sizeof(uint8_t); //first opcode byte 254 255 unsigned cbInc = ParseInstruction(uInstrAddr + i, &paOneByteMap[pCpu->opcode], pCpu); 256 257 AssertMsg(pCpu->opsize == cbPrefix + cbInc + sizeof(uint8_t), 258 ("%u %u\n", pCpu->opsize, cbPrefix + cbInc + sizeof(uint8_t))); 259 pCpu->opsize = cbPrefix + cbInc + sizeof(uint8_t); 260 261 if (pszOutput) 262 disasmSprintf(pszOutput, uInstrAddr+i-1-cbPrefix, pCpu, &pCpu->param1, &pCpu->param2, &pCpu->param3); 263 264 i += cbInc; 265 cbPrefix = 0; 266 break; 291 267 } 292 268 … … 297 273 disValidateLockSequence(pCpu); 298 274 299 return VINF_SUCCESS; 300 } 301 //***************************************************************************** 302 //***************************************************************************** 303 char *DbgBytesToString(PDISCPUSTATE pCpu, RTUINTPTR pBytes, int size, char *pszOutput) 304 { 305 char *psz = strchr(pszOutput, '\0'); 306 size_t len; 307 int i; 308 309 for(len = psz - pszOutput; len < 40; len++) 310 *psz++ = ' '; 311 *psz++ = ' '; 312 *psz++ = '['; 313 314 for(i = 0; (int)i < size; i++) 315 psz += RTStrPrintf(psz, 64, "%02X ", DISReadByte(pCpu, pBytes+i)); 316 317 psz[-1] = ']'; // replaces space 318 319 return pszOutput; 320 } 321 //***************************************************************************** 322 //***************************************************************************** 323 void disasmSprintf(char *pszOutput, RTUINTPTR pu8Instruction, PDISCPUSTATE pCpu, OP_PARAMETER *pParam1, OP_PARAMETER *pParam2, OP_PARAMETER *pParam3) 324 { 325 const char *lpszFormat = pCpu->pszOpcode; 275 return pCpu->rc; 276 } 277 //***************************************************************************** 278 //***************************************************************************** 279 static size_t DbgBytesToString(PDISCPUSTATE pCpu, char *pszOutput, size_t offStart) 280 { 281 unsigned off = offStart; 282 283 while (off < 40) 284 pszOutput[off++] = ' '; 285 pszOutput[off++] = ' '; 286 pszOutput[off++] = '['; 287 288 for (unsigned i = 0; i < pCpu->opsize; i++) 289 off += RTStrPrintf(&pszOutput[off], 64, "%02X ", pCpu->abInstr[i]); 290 291 pszOutput[off - 1] = ']'; // replaces space 292 return off - offStart; 293 } 294 //***************************************************************************** 295 //***************************************************************************** 296 void disasmSprintf(char *pszOutput, RTUINTPTR uInstrAddr, PDISCPUSTATE pCpu, 297 OP_PARAMETER *pParam1, OP_PARAMETER *pParam2, OP_PARAMETER *pParam3) 298 { 299 const char *pszFormat = pCpu->pszOpcode; 326 300 int param = 1; 327 301 328 RTStrPrintf(pszOutput, 64, "%08X: ", (unsigned)pCpu->opaddr); 329 if(pCpu->prefix & PREFIX_LOCK) 302 303 size_t off = RTStrPrintf(pszOutput, 64, "%08RTptr: ", pCpu->opaddr); 304 if (pCpu->prefix & PREFIX_LOCK) 305 off += RTStrPrintf(&pszOutput[off], 64, "lock "); 306 if (pCpu->prefix & PREFIX_REP) 307 off += RTStrPrintf(&pszOutput[off], 64, "rep(e) "); 308 else if(pCpu->prefix & PREFIX_REPNE) 309 off += RTStrPrintf(&pszOutput[off], 64, "repne "); 310 311 if (!strcmp("Invalid Opcode", pszFormat)) 330 312 { 331 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "lock "); 332 } 333 if(pCpu->prefix & PREFIX_REP) 334 { 335 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "rep(e) "); 313 if (pCpu->opsize >= 2) 314 off += RTStrPrintf(&pszOutput[off], 64, "Invalid Opcode [%02X][%02X]", pCpu->abInstr[0], pCpu->abInstr[1]); 315 else 316 off += RTStrPrintf(&pszOutput[off], 64, "Invalid Opcode [%02X]", pCpu->abInstr[0]); 336 317 } 337 318 else 338 if(pCpu->prefix & PREFIX_REPNE) 339 { 340 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "repne "); 341 } 342 343 if(!strcmp("Invalid Opcode", lpszFormat)) 344 { 345 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "Invalid Opcode [%02X][%02X]", DISReadByte(pCpu, pu8Instruction), DISReadByte(pCpu, pu8Instruction+1) ); 346 } 347 else 348 while(*lpszFormat) 349 { 350 switch(*lpszFormat) 319 while (*pszFormat) 351 320 { 352 case '%': 353 switch(*(lpszFormat+1)) 321 switch (*pszFormat) 354 322 { 355 case 'J': //Relative jump offset 356 { 357 int32_t disp; 358 359 AssertMsg(param == 1, ("Invalid branch parameter nr")); 360 if(pParam1->flags & USE_IMMEDIATE8_REL) 323 case '%': 324 switch (pszFormat[1]) 361 325 { 362 disp = (int32_t)(char)pParam1->parval; 326 case 'J': //Relative jump offset 327 { 328 int32_t disp; 329 330 AssertMsg(param == 1, ("Invalid branch parameter nr")); 331 if (pParam1->flags & USE_IMMEDIATE8_REL) 332 disp = (int32_t)(char)pParam1->parval; 333 else if (pParam1->flags & USE_IMMEDIATE16_REL) 334 disp = (int32_t)(uint16_t)pParam1->parval; 335 else if (pParam1->flags & USE_IMMEDIATE32_REL) 336 disp = (int32_t)pParam1->parval; 337 else if(pParam1->flags & USE_IMMEDIATE64_REL) 338 /** @todo: is this correct? */ 339 disp = (int32_t)pParam1->parval; 340 else 341 { 342 AssertMsgFailed(("Oops!\n")); 343 return; 344 } 345 uint32_t addr = (uint32_t)(pCpu->opaddr + pCpu->opsize) + disp; 346 off += RTStrPrintf(&pszOutput[off], 64, "[%08X]", addr); 363 347 } 364 else 365 if(pParam1->flags & USE_IMMEDIATE16_REL) 366 { 367 disp = (int32_t)(uint16_t)pParam1->parval; 368 } 369 else 370 if(pParam1->flags & USE_IMMEDIATE32_REL) 371 { 372 disp = (int32_t)pParam1->parval; 373 } 374 else 375 if(pParam1->flags & USE_IMMEDIATE64_REL) 376 { 377 /* @todo: is this correct? */ 378 disp = (int32_t)pParam1->parval; 379 } 380 else 381 { 348 349 //no break; 350 351 case 'A': //direct address 352 case 'C': //control register 353 case 'D': //debug register 354 case 'E': //ModRM specifies parameter 355 case 'F': //Eflags register 356 case 'G': //ModRM selects general register 357 case 'I': //Immediate data 358 case 'M': //ModRM may only refer to memory 359 case 'O': //No ModRM byte 360 case 'P': //ModRM byte selects MMX register 361 case 'Q': //ModRM byte selects MMX register or memory address 362 case 'R': //ModRM byte may only refer to a general register 363 case 'S': //ModRM byte selects a segment register 364 case 'T': //ModRM byte selects a test register 365 case 'V': //ModRM byte selects an XMM/SSE register 366 case 'W': //ModRM byte selects an XMM/SSE register or a memory address 367 case 'X': //DS:SI 368 case 'Y': //ES:DI 369 switch(param) 370 { 371 case 1: 372 off += RTStrPrintf(&pszOutput[off], 64, pParam1->szParam); 373 break; 374 case 2: 375 off += RTStrPrintf(&pszOutput[off], 64, pParam2->szParam); 376 break; 377 case 3: 378 off += RTStrPrintf(&pszOutput[off], 64, pParam3->szParam); 379 break; 380 } 381 break; 382 383 case 'e': //register based on operand size (e.g. %eAX) 384 if(pCpu->opmode == CPUMODE_32BIT) 385 off += RTStrPrintf(&pszOutput[off], 64, "E"); 386 if(pCpu->opmode == CPUMODE_64BIT) 387 off += RTStrPrintf(&pszOutput[off], 64, "R"); 388 389 off += RTStrPrintf(&pszOutput[off], 64, "%c%c", pszFormat[2], pszFormat[3]); 390 break; 391 392 default: 382 393 AssertMsgFailed(("Oops!\n")); 383 return;384 }385 uint32_t addr = (uint32_t)(pCpu->opaddr + pCpu->opsize) + disp;386 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "[%08X]", addr);387 }388 389 //no break;390 391 case 'A': //direct address392 case 'C': //control register393 case 'D': //debug register394 case 'E': //ModRM specifies parameter395 case 'F': //Eflags register396 case 'G': //ModRM selects general register397 case 'I': //Immediate data398 case 'M': //ModRM may only refer to memory399 case 'O': //No ModRM byte400 case 'P': //ModRM byte selects MMX register401 case 'Q': //ModRM byte selects MMX register or memory address402 case 'R': //ModRM byte may only refer to a general register403 case 'S': //ModRM byte selects a segment register404 case 'T': //ModRM byte selects a test register405 case 'V': //ModRM byte selects an XMM/SSE register406 case 'W': //ModRM byte selects an XMM/SSE register or a memory address407 case 'X': //DS:SI408 case 'Y': //ES:DI409 switch(param)410 {411 case 1:412 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, pParam1->szParam);413 break;414 case 2:415 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, pParam2->szParam);416 break;417 case 3:418 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, pParam3->szParam);419 394 break; 420 395 } 396 397 //Go to the next parameter in the format string 398 while (*pszFormat && *pszFormat != ',') 399 pszFormat++; 400 if (*pszFormat == ',') 401 pszFormat--; 402 421 403 break; 422 404 423 case 'e': //register based on operand size (e.g. %eAX) 424 if(pCpu->opmode == CPUMODE_32BIT) 425 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "E"); 426 if(pCpu->opmode == CPUMODE_64BIT) 427 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "R"); 428 429 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "%c%c", lpszFormat[2], lpszFormat[3]); 430 break; 405 case ',': 406 param++; 407 //no break 431 408 432 409 default: 433 AssertMsgFailed(("Oops!\n"));410 off += RTStrPrintf(&pszOutput[off], 64, "%c", *pszFormat); 434 411 break; 435 412 } 436 413 437 //Go to the next parameter in the format string 438 while(*lpszFormat && *lpszFormat != ',') lpszFormat++; 439 if(*lpszFormat == ',') lpszFormat--; 440 441 break; 442 443 case ',': 444 param++; 445 //no break 446 447 default: 448 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "%c", *lpszFormat); 449 break; 414 if (*pszFormat) 415 pszFormat++; 450 416 } 451 417 452 if(*lpszFormat) lpszFormat++; 453 } 454 DbgBytesToString(pCpu, pu8Instruction, pCpu->opsize, pszOutput); 455 RTStrPrintf(&pszOutput[strlen(pszOutput)], 64, "\n"); 456 } 457 //***************************************************************************** 458 //***************************************************************************** 418 off += DbgBytesToString(pCpu, pszOutput, off); 419 off += RTStrPrintf(&pszOutput[off], 64, "\n"); 420 } 421 //***************************************************************************** 422 //***************************************************************************** -
trunk/src/VBox/Disassembler/DisasmCore.cpp
r41494 r41658 1 /* $Id$ */ 1 2 /** @file 2 * 3 * VBox disassembler: 4 * Core components 3 * VBox Disassembler - Core Components. 5 4 */ 6 5 7 6 /* 8 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2012 Oracle Corporation 9 8 * 10 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 45 44 * Internal Functions * 46 45 *******************************************************************************/ 47 static int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction); 46 static int disCoreParseInstr(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, const OPCODE *paOneByteMap, 47 unsigned *pcbInstruction); 48 48 #if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED) 49 49 static void disasmAddString(char *psz, const char *pszString); … … 160 160 }; 161 161 162 /**163 * Parses one instruction.164 * The result is found in pCpu.165 *166 * @returns Success indicator.167 * @param pCpu Pointer to cpu structure which has DISCPUSTATE::mode set correctly.168 * @param InstructionAddr Pointer to the instruction to parse.169 * @param pcbInstruction Where to store the size of the instruction.170 * NULL is allowed.171 */172 DISDECL(int) DISCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction)173 {174 /*175 * Reset instruction settings176 */177 pCpu->prefix = PREFIX_NONE;178 pCpu->enmPrefixSeg = DIS_SELREG_DS;179 pCpu->lastprefix = 0;180 pCpu->ModRM.u = 0;181 pCpu->SIB.u = 0;182 pCpu->param1.parval = 0;183 pCpu->param2.parval = 0;184 pCpu->param3.parval = 0;185 pCpu->param1.szParam[0] = '\0';186 pCpu->param2.szParam[0] = '\0';187 pCpu->param3.szParam[0] = '\0';188 pCpu->param1.flags = 0;189 pCpu->param2.flags = 0;190 pCpu->param3.flags = 0;191 pCpu->param1.size = 0;192 pCpu->param2.size = 0;193 pCpu->param3.size = 0;194 pCpu->pfnReadBytes = 0;195 pCpu->uFilter = OPTYPE_ALL;196 pCpu->pfnDisasmFnTable = pfnFullDisasm;197 198 return RT_SUCCESS(disCoreOne(pCpu, InstructionAddr, pcbInstruction));199 }200 162 201 163 /** … … 204 166 * 205 167 * @returns VBox status code. 206 * @param InstructionAddrAddress of the instruction to decode. What this means168 * @param uInstrAddr Address of the instruction to decode. What this means 207 169 * is left to the pfnReadBytes function. 208 170 * @param enmCpuMode The CPU mode. CPUMODE_32BIT, CPUMODE_16BIT, or CPUMODE_64BIT. … … 213 175 * NULL is allowed. 214 176 */ 215 DISDECL(int) DISCoreOneEx(RTUINTPTR InstructionAddr, DISCPUMODE enmCpuMode, PFN_DIS_READBYTES pfnReadBytes, void *pvUser,177 DISDECL(int) DISCoreOneEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser, 216 178 PDISCPUSTATE pCpu, unsigned *pcbInstruction) 217 179 { 180 const OPCODE *paOneByteMap; 181 218 182 /* 219 * Reset instruction settings 183 * Initialize the CPU state. 184 * Note! The RT_BZERO make ASSUMPTIONS about the placement of apvUserData. 220 185 */ 186 RT_BZERO(pCpu, RT_OFFSETOF(DISCPUSTATE, apvUserData)); 187 188 pCpu->mode = enmCpuMode; 189 if (enmCpuMode == CPUMODE_64BIT) 190 { 191 paOneByteMap = g_aOneByteMapX64; 192 pCpu->addrmode = CPUMODE_64BIT; 193 pCpu->opmode = CPUMODE_32BIT; 194 } 195 else 196 { 197 paOneByteMap = g_aOneByteMapX86; 198 pCpu->addrmode = enmCpuMode; 199 pCpu->opmode = enmCpuMode; 200 } 221 201 pCpu->prefix = PREFIX_NONE; 222 202 pCpu->enmPrefixSeg = DIS_SELREG_DS; 223 pCpu->lastprefix = 0; 224 pCpu->mode = enmCpuMode; 225 pCpu->ModRM.u = 0; 226 pCpu->SIB.u = 0; 227 pCpu->param1.parval = 0; 228 pCpu->param2.parval = 0; 229 pCpu->param3.parval = 0; 230 pCpu->param1.szParam[0] = '\0'; 231 pCpu->param2.szParam[0] = '\0'; 232 pCpu->param3.szParam[0] = '\0'; 233 pCpu->param1.flags = 0; 234 pCpu->param2.flags = 0; 235 pCpu->param3.flags = 0; 236 pCpu->param1.size = 0; 237 pCpu->param2.size = 0; 238 pCpu->param3.size = 0; 239 pCpu->pfnReadBytes = pfnReadBytes; 203 pCpu->uInstrAddr = uInstrAddr; 204 pCpu->pfnDisasmFnTable = pfnFullDisasm; 205 pCpu->uFilter = OPTYPE_ALL; 206 pCpu->rc = VINF_SUCCESS; 207 pCpu->pfnReadBytes = pfnReadBytes ? pfnReadBytes : disReadBytesDefault; 240 208 pCpu->apvUserData[0] = pvUser; 241 pCpu->uFilter = OPTYPE_ALL; 242 pCpu->pfnDisasmFnTable = pfnFullDisasm; 243 244 return disCoreOne(pCpu, InstructionAddr, pcbInstruction); 209 210 return disCoreParseInstr(pCpu, uInstrAddr, paOneByteMap, pcbInstruction); 245 211 } 246 212 … … 250 216 * @returns VBox status code. 251 217 * @param pCpu Initialized cpu state. 252 * @param InstructionAddr Instruction address. 218 * @param paOneByteMap The one byte opcode map to use. 219 * @param uInstrAddr Instruction address. 253 220 * @param pcbInstruction Where to store the instruction size. Can be NULL. 254 221 */ 255 static int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction) 256 { 257 const OPCODE *paOneByteMap; 258 222 static int disCoreParseInstr(PDISCPUSTATE pCpu, RTUINTPTR uInstrAddr, const OPCODE *paOneByteMap, unsigned *pcbInstruction) 223 { 259 224 /* 260 225 * Parse byte by byte. … … 262 227 unsigned iByte = 0; 263 228 unsigned cbInc; 264 265 if (pCpu->mode == CPUMODE_64BIT) 266 { 267 paOneByteMap = g_aOneByteMapX64; 268 pCpu->addrmode = CPUMODE_64BIT; 269 pCpu->opmode = CPUMODE_32BIT; 270 } 271 else 272 { 273 paOneByteMap = g_aOneByteMapX86; 274 pCpu->addrmode = pCpu->mode; 275 pCpu->opmode = pCpu->mode; 276 } 277 278 #ifdef IN_RING3 279 # ifndef __L4ENV__ /* Unfortunately, we have no exception handling in l4env */ 280 try 281 # else 282 pCpu->pJumpBuffer = &jumpbuffer; 283 if (setjmp(jumpbuffer) == 0) 284 # endif 285 #endif 286 { 287 while(1) 229 for (;;) 230 { 231 uint8_t codebyte = DISReadByte(pCpu, uInstrAddr+iByte); 232 uint8_t opcode = paOneByteMap[codebyte].opcode; 233 234 /* Hardcoded assumption about OP_* values!! */ 235 if (opcode <= OP_LAST_PREFIX) 288 236 { 289 uint8_t codebyte = DISReadByte(pCpu, InstructionAddr+iByte); 290 uint8_t opcode = paOneByteMap[codebyte].opcode; 291 292 /* Hardcoded assumption about OP_* values!! */ 293 if (opcode <= OP_LAST_PREFIX) 237 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */ 238 if (opcode != OP_REX) 294 239 { 295 /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */ 296 if (opcode != OP_REX) 240 /** Last prefix byte (for SSE2 extension tables); don't include the REX prefix */ 241 pCpu->lastprefix = opcode; 242 pCpu->prefix &= ~PREFIX_REX; 243 } 244 245 switch (opcode) 246 { 247 case OP_INVALID: 248 if (pcbInstruction) 249 *pcbInstruction = iByte + 1; 250 return pCpu->rc = VERR_DIS_INVALID_OPCODE; 251 252 // segment override prefix byte 253 case OP_SEG: 254 pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START); 255 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */ 256 if ( pCpu->mode != CPUMODE_64BIT 257 || pCpu->enmPrefixSeg >= DIS_SELREG_FS) 297 258 { 298 /** Last prefix byte (for SSE2 extension tables); don't include the REX prefix */ 299 pCpu->lastprefix = opcode; 300 pCpu->prefix &= ~PREFIX_REX; 259 pCpu->prefix |= PREFIX_SEG; 301 260 } 302 303 switch (opcode) 304 { 305 case OP_INVALID: 306 #if 0 307 AssertMsgFailed(("Invalid opcode!!\n")); 308 #endif 309 return VERR_DIS_INVALID_OPCODE; 310 311 // segment override prefix byte 312 case OP_SEG: 313 pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START); 314 /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */ 315 if ( pCpu->mode != CPUMODE_64BIT 316 || pCpu->enmPrefixSeg >= DIS_SELREG_FS) 317 { 318 pCpu->prefix |= PREFIX_SEG; 319 } 320 iByte += sizeof(uint8_t); 321 continue; //fetch the next byte 322 323 // lock prefix byte 324 case OP_LOCK: 325 pCpu->prefix |= PREFIX_LOCK; 326 iByte += sizeof(uint8_t); 327 continue; //fetch the next byte 328 329 // address size override prefix byte 330 case OP_ADDRSIZE: 331 pCpu->prefix |= PREFIX_ADDRSIZE; 332 if (pCpu->mode == CPUMODE_16BIT) 333 pCpu->addrmode = CPUMODE_32BIT; 334 else 335 if (pCpu->mode == CPUMODE_32BIT) 336 pCpu->addrmode = CPUMODE_16BIT; 337 else 338 pCpu->addrmode = CPUMODE_32BIT; /* 64 bits */ 339 340 iByte += sizeof(uint8_t); 341 continue; //fetch the next byte 342 343 // operand size override prefix byte 344 case OP_OPSIZE: 345 pCpu->prefix |= PREFIX_OPSIZE; 346 if (pCpu->mode == CPUMODE_16BIT) 347 pCpu->opmode = CPUMODE_32BIT; 348 else 349 pCpu->opmode = CPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */ 350 351 iByte += sizeof(uint8_t); 352 continue; //fetch the next byte 353 354 // rep and repne are not really prefixes, but we'll treat them as such 355 case OP_REPE: 356 pCpu->prefix |= PREFIX_REP; 357 iByte += sizeof(uint8_t); 358 continue; //fetch the next byte 359 360 case OP_REPNE: 361 pCpu->prefix |= PREFIX_REPNE; 362 iByte += sizeof(uint8_t); 363 continue; //fetch the next byte 364 365 case OP_REX: 366 Assert(pCpu->mode == CPUMODE_64BIT); 367 /* REX prefix byte */ 368 pCpu->prefix |= PREFIX_REX; 369 pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1); 370 iByte += sizeof(uint8_t); 371 372 if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W) 373 pCpu->opmode = CPUMODE_64BIT; /* overrides size prefix byte */ 374 continue; //fetch the next byte 375 } 261 iByte += sizeof(uint8_t); 262 continue; //fetch the next byte 263 264 // lock prefix byte 265 case OP_LOCK: 266 pCpu->prefix |= PREFIX_LOCK; 267 iByte += sizeof(uint8_t); 268 continue; //fetch the next byte 269 270 // address size override prefix byte 271 case OP_ADDRSIZE: 272 pCpu->prefix |= PREFIX_ADDRSIZE; 273 if (pCpu->mode == CPUMODE_16BIT) 274 pCpu->addrmode = CPUMODE_32BIT; 275 else 276 if (pCpu->mode == CPUMODE_32BIT) 277 pCpu->addrmode = CPUMODE_16BIT; 278 else 279 pCpu->addrmode = CPUMODE_32BIT; /* 64 bits */ 280 281 iByte += sizeof(uint8_t); 282 continue; //fetch the next byte 283 284 // operand size override prefix byte 285 case OP_OPSIZE: 286 pCpu->prefix |= PREFIX_OPSIZE; 287 if (pCpu->mode == CPUMODE_16BIT) 288 pCpu->opmode = CPUMODE_32BIT; 289 else 290 pCpu->opmode = CPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */ 291 292 iByte += sizeof(uint8_t); 293 continue; //fetch the next byte 294 295 // rep and repne are not really prefixes, but we'll treat them as such 296 case OP_REPE: 297 pCpu->prefix |= PREFIX_REP; 298 iByte += sizeof(uint8_t); 299 continue; //fetch the next byte 300 301 case OP_REPNE: 302 pCpu->prefix |= PREFIX_REPNE; 303 iByte += sizeof(uint8_t); 304 continue; //fetch the next byte 305 306 case OP_REX: 307 Assert(pCpu->mode == CPUMODE_64BIT); 308 /* REX prefix byte */ 309 pCpu->prefix |= PREFIX_REX; 310 pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1); 311 iByte += sizeof(uint8_t); 312 313 if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W) 314 pCpu->opmode = CPUMODE_64BIT; /* overrides size prefix byte */ 315 continue; //fetch the next byte 376 316 } 377 378 unsigned uIdx = iByte; 379 iByte += sizeof(uint8_t); //first opcode byte 380 381 pCpu->opaddr = InstructionAddr; 382 pCpu->opcode = codebyte; 383 384 cbInc = ParseInstruction(InstructionAddr + iByte, &paOneByteMap[pCpu->opcode], pCpu); 385 iByte += cbInc; 386 break; 387 } 388 } 389 #ifdef IN_RING3 390 # ifndef __L4ENV__ 391 catch(...) 392 # else 393 else /* setjmp has returned a non-zero value: an exception occurred */ 394 # endif 395 { 396 pCpu->opsize = 0; 397 return VERR_DIS_GEN_FAILURE; 398 } 399 #endif 400 317 } 318 319 unsigned uIdx = iByte; 320 iByte += sizeof(uint8_t); //first opcode byte 321 322 pCpu->opaddr = uInstrAddr; 323 pCpu->opcode = codebyte; 324 325 cbInc = ParseInstruction(uInstrAddr + iByte, &paOneByteMap[pCpu->opcode], pCpu); 326 iByte += cbInc; 327 break; 328 } 329 330 AssertMsg(pCpu->opsize == iByte || RT_FAILURE_NP(pCpu->rc), ("%u %u\n", pCpu->opsize, iByte)); 401 331 pCpu->opsize = iByte; 402 332 if (pcbInstruction) … … 406 336 disValidateLockSequence(pCpu); 407 337 408 return VINF_SUCCESS;338 return pCpu->rc; 409 339 } 410 340 //***************************************************************************** … … 619 549 { 620 550 pParam->flags |= USE_DISPLACEMENT32; 621 pParam->disp32 = pCpu-> disp;551 pParam->disp32 = pCpu->i32SibDisp; 622 552 disasmAddChar(pParam->szParam, '+'); 623 553 disasmPrintDisp32(pParam); … … 626 556 { /* sign-extend to 64 bits */ 627 557 pParam->flags |= USE_DISPLACEMENT64; 628 pParam->disp64 = pCpu-> disp;558 pParam->disp64 = pCpu->i32SibDisp; 629 559 disasmAddChar(pParam->szParam, '+'); 630 560 disasmPrintDisp64(pParam); … … 666 596 { 667 597 /* Additional 32 bits displacement. No change in long mode. */ 668 pCpu-> disp = DISReadDWord(pCpu, lpszCodeBlock);598 pCpu->i32SibDisp = DISReadDWord(pCpu, lpszCodeBlock); 669 599 size += sizeof(int32_t); 670 600 } … … 807 737 { 808 738 pParam->flags |= USE_DISPLACEMENT32; 809 pParam->disp32 = pCpu-> disp;739 pParam->disp32 = pCpu->i32SibDisp; 810 740 disasmPrintDisp32(pParam); 811 741 } … … 813 743 { 814 744 pParam->flags |= USE_RIPDISPLACEMENT32; 815 pParam->disp32 = pCpu-> disp;745 pParam->disp32 = pCpu->i32SibDisp; 816 746 disasmAddString(pParam->szParam, "RIP+"); 817 747 disasmPrintDisp32(pParam); … … 836 766 disasmModRMReg(pCpu, pOp, rm, pParam, 1); 837 767 } 838 pParam->disp8 = pCpu-> disp;768 pParam->disp8 = pCpu->i32SibDisp; 839 769 pParam->flags |= USE_DISPLACEMENT8; 840 770 … … 859 789 disasmModRMReg(pCpu, pOp, rm, pParam, 1); 860 790 } 861 pParam->disp32 = pCpu-> disp;791 pParam->disp32 = pCpu->i32SibDisp; 862 792 pParam->flags |= USE_DISPLACEMENT32; 863 793 … … 884 814 if (rm == 6) 885 815 {//16 bits displacement 886 pParam->disp16 = pCpu-> disp;816 pParam->disp16 = pCpu->i32SibDisp; 887 817 pParam->flags |= USE_DISPLACEMENT16; 888 818 disasmPrintDisp16(pParam); … … 900 830 disasmAddChar(pParam->szParam, '['); 901 831 disasmModRMReg16(pCpu, pOp, rm, pParam); 902 pParam->disp8 = pCpu-> disp;832 pParam->disp8 = pCpu->i32SibDisp; 903 833 pParam->flags |= USE_BASE | USE_DISPLACEMENT8; 904 834 … … 916 846 disasmAddChar(pParam->szParam, '['); 917 847 disasmModRMReg16(pCpu, pOp, rm, pParam); 918 pParam->disp16 = pCpu-> disp;848 pParam->disp16 = pCpu->i32SibDisp; 919 849 pParam->flags |= USE_BASE | USE_DISPLACEMENT16; 920 850 … … 968 898 case 0: /* Effective address */ 969 899 if (rm == 5) { /* 32 bits displacement */ 970 pCpu-> disp = DISReadDWord(pCpu, lpszCodeBlock);900 pCpu->i32SibDisp = DISReadDWord(pCpu, lpszCodeBlock); 971 901 size += sizeof(int32_t); 972 902 } … … 975 905 976 906 case 1: /* Effective address + 8 bits displacement */ 977 pCpu-> disp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);907 pCpu->i32SibDisp = (int8_t)DISReadByte(pCpu, lpszCodeBlock); 978 908 size += sizeof(char); 979 909 break; 980 910 981 911 case 2: /* Effective address + 32 bits displacement */ 982 pCpu-> disp = DISReadDWord(pCpu, lpszCodeBlock);912 pCpu->i32SibDisp = DISReadDWord(pCpu, lpszCodeBlock); 983 913 size += sizeof(int32_t); 984 914 break; … … 995 925 case 0: /* Effective address */ 996 926 if (rm == 6) { 997 pCpu-> disp = DISReadWord(pCpu, lpszCodeBlock);927 pCpu->i32SibDisp = DISReadWord(pCpu, lpszCodeBlock); 998 928 size += sizeof(uint16_t); 999 929 } … … 1002 932 1003 933 case 1: /* Effective address + 8 bits displacement */ 1004 pCpu-> disp = (int8_t)DISReadByte(pCpu, lpszCodeBlock);934 pCpu->i32SibDisp = (int8_t)DISReadByte(pCpu, lpszCodeBlock); 1005 935 size += sizeof(char); 1006 936 break; 1007 937 1008 938 case 2: /* Effective address + 32 bits displacement */ 1009 pCpu-> disp = (int16_t)DISReadWord(pCpu, lpszCodeBlock);939 pCpu->i32SibDisp = (int16_t)DISReadWord(pCpu, lpszCodeBlock); 1010 940 size += sizeof(uint16_t); 1011 941 break; … … 2473 2403 2474 2404 default: 2475 #ifdef IN_RING32476 2405 Log(("disasmModRMReg %x:%x failed!!\n", type, subtype)); 2477 DIS_THROW(ExceptionInvalidModRM); 2478 #else 2479 AssertMsgFailed(("Oops!\n")); 2480 #endif 2406 pCpu->rc = VERR_DIS_INVALID_MODRM; 2481 2407 break; 2482 2408 } … … 2500 2426 void disasmModRMSReg(PDISCPUSTATE pCpu, PCOPCODE pOp, unsigned idx, POP_PARAMETER pParam) 2501 2427 { 2502 NOREF(pCpu); NOREF(pOp); 2503 #if 0 //def DEBUG_Sander 2504 AssertMsg(idx < RT_ELEMENTS(szModRMSegReg), ("idx=%d\n", idx)); 2505 #endif 2506 #ifdef IN_RING3 2428 NOREF(pOp); 2507 2429 if (idx >= RT_ELEMENTS(szModRMSegReg)) 2508 2430 { 2509 2431 Log(("disasmModRMSReg %d failed!!\n", idx)); 2510 DIS_THROW(ExceptionInvalidParameter); 2511 } 2512 #endif 2513 2514 idx = RT_MIN(idx, RT_ELEMENTS(szModRMSegReg)-1); 2432 pCpu->rc = VERR_DIS_INVALID_PARAMETER; 2433 return; 2434 } 2435 2515 2436 disasmAddString(pParam->szParam, szModRMSegReg[idx]); 2516 2437 pParam->flags |= USE_REG_SEG; … … 2610 2531 disasmAddStringF1(pParam->szParam, "%s:", szModRMSegReg[pCpu->enmPrefixSeg]); 2611 2532 } 2612 //***************************************************************************** 2613 /* Read functions for getting the opcode bytes */ 2614 //***************************************************************************** 2615 uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress) 2616 { 2617 if (pCpu->pfnReadBytes) 2618 { 2619 uint8_t temp = 0; 2620 int rc; 2621 2622 rc = pCpu->pfnReadBytes(pAddress, &temp, sizeof(temp), pCpu); 2623 if (RT_FAILURE(rc)) 2624 { 2625 Log(("DISReadByte failed!!\n")); 2626 DIS_THROW(ExceptionMemRead); 2627 } 2628 return temp; 2629 } 2630 #ifdef IN_RING0 2631 AssertMsgFailed(("DISReadByte with no read callback in ring 0!!\n")); 2632 return 0; 2633 #else 2634 return *(uint8_t *)(uintptr_t)pAddress; 2635 #endif 2636 } 2637 //***************************************************************************** 2638 //***************************************************************************** 2639 uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress) 2640 { 2641 if (pCpu->pfnReadBytes) 2642 { 2643 uint16_t temp = 0; 2644 int rc; 2645 2646 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu); 2647 if (RT_FAILURE(rc)) 2648 { 2649 Log(("DISReadWord failed!!\n")); 2650 DIS_THROW(ExceptionMemRead); 2651 } 2652 return temp; 2653 } 2533 2534 2535 /** 2536 * Slow path for storing instruction bytes. 2537 * 2538 * @param pCpu The disassembler state. 2539 * @param uAddress The address. 2540 * @param pbSrc The bytes. 2541 * @param cbSrc The number of bytes. 2542 */ 2543 DECL_NO_INLINE(static, void) 2544 disStoreInstrBytesSlow(PDISCPUSTATE pCpu, RTUINTPTR uAddress, const uint8_t *pbSrc, size_t cbSrc) 2545 { 2546 /* 2547 * Figure out which case it is. 2548 */ 2549 uint32_t cbInstr = pCpu->opsize; 2550 RTUINTPTR off = uAddress - pCpu->uInstrAddr; 2551 if (off < cbInstr) 2552 { 2553 if (off + cbSrc <= cbInstr) 2554 { 2555 AssertMsg(memcmp(&pCpu->abInstr[off], pbSrc, cbSrc) == 0, 2556 ("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr)); 2557 return; /* fully re-reading old stuff. */ 2558 } 2559 2560 /* Only partially re-reading stuff, skip ahead and add the rest. */ 2561 uint32_t cbAlreadyRead = cbInstr - (uint32_t)off; 2562 Assert(memcmp(&pCpu->abInstr[off], pbSrc, cbAlreadyRead) == 0); 2563 uAddress += cbAlreadyRead; 2564 pbSrc += cbAlreadyRead; 2565 cbSrc -= cbAlreadyRead; 2566 } 2567 2568 if (off >= sizeof(cbInstr)) 2569 { 2570 /* The instruction is too long! This shouldn't happen. */ 2571 AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr)); 2572 return; 2573 } 2574 else if (off > cbInstr) 2575 { 2576 /* Mind the gap - this shouldn't happen, but read the gap bytes if it does. */ 2577 AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.16Rhxs)", uAddress, cbSrc, off, cbInstr, pCpu->abInstr)); 2578 uint32_t cbGap = off - cbInstr; 2579 int rc = pCpu->pfnReadBytes(pCpu, &pCpu->abInstr[cbInstr], uAddress - cbGap, cbGap); 2580 if (RT_FAILURE(rc)) 2581 { 2582 pCpu->rc = VERR_DIS_MEM_READ; 2583 RT_BZERO(&pCpu->abInstr[cbInstr], cbGap); 2584 } 2585 pCpu->opsize = cbInstr = off; 2586 } 2587 2588 /* 2589 * Copy the bytes. 2590 */ 2591 if (off + cbSrc <= sizeof(pCpu->abInstr)) 2592 { 2593 memcpy(&pCpu->abInstr[cbInstr], pbSrc, cbSrc); 2594 pCpu->opsize = cbInstr + cbSrc; 2595 } 2596 else 2597 { 2598 uint32_t cbToCopy = sizeof(pCpu->abInstr) - off; 2599 memcpy(&pCpu->abInstr[cbInstr], pbSrc, cbToCopy); 2600 pCpu->opsize = sizeof(pCpu->abInstr); 2601 AssertMsgFailed(("%RTptr LB %zx off=%RTptr (%.*Rhxs)", uAddress, cbSrc, off, sizeof(pCpu->abInstr), pCpu->abInstr)); 2602 } 2603 } 2604 2605 DECLCALLBACK(int) disReadBytesDefault(PDISCPUSTATE pCpu, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead) 2606 { 2654 2607 #ifdef IN_RING0 2655 2608 AssertMsgFailed(("DISReadWord with no read callback in ring 0!!\n")); 2656 return 0; 2609 RT_BZERO(pbDst, cbToRead); 2610 return VERR_DIS_NO_READ_CALLBACK; 2657 2611 #else 2658 return *(uint16_t *)(uintptr_t)pAddress; 2612 memcpy(pbDst, (void const *)(uintptr_t)uSrcAddr, cbToRead); 2613 return VINF_SUCCESS; 2659 2614 #endif 2660 2615 } 2661 //***************************************************************************** 2662 //***************************************************************************** 2663 uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress) 2664 { 2665 if (pCpu->pfnReadBytes) 2666 { 2667 uint32_t temp = 0; 2668 int rc; 2669 2670 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu); 2671 if (RT_FAILURE(rc)) 2672 { 2673 Log(("DISReadDWord failed!!\n")); 2674 DIS_THROW(ExceptionMemRead); 2675 } 2676 return temp; 2677 } 2678 #ifdef IN_RING0 2679 AssertMsgFailed(("DISReadDWord with no read callback in ring 0!!\n")); 2680 return 0; 2681 #else 2682 return *(uint32_t *)(uintptr_t)pAddress; 2683 #endif 2684 } 2685 //***************************************************************************** 2686 //***************************************************************************** 2687 uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress) 2688 { 2689 if (pCpu->pfnReadBytes) 2690 { 2691 uint64_t temp = 0; 2692 int rc; 2693 2694 rc = pCpu->pfnReadBytes(pAddress, (uint8_t*)&temp, sizeof(temp), pCpu); 2695 if (RT_FAILURE(rc)) 2696 { 2697 Log(("DISReadQWord %x failed!!\n", pAddress)); 2698 DIS_THROW(ExceptionMemRead); 2699 } 2700 2701 return temp; 2702 } 2703 #ifdef IN_RING0 2704 AssertMsgFailed(("DISReadQWord with no read callback in ring 0!!\n")); 2705 return 0; 2706 #else 2707 return *(uint64_t *)(uintptr_t)pAddress; 2708 #endif 2616 2617 //***************************************************************************** 2618 /* Read functions for getting the opcode bytes */ 2619 //***************************************************************************** 2620 uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR uAddress) 2621 { 2622 uint8_t bTemp = 0; 2623 int rc = pCpu->pfnReadBytes(pCpu, &bTemp, uAddress, sizeof(bTemp)); 2624 if (RT_FAILURE(rc)) 2625 { 2626 Log(("DISReadByte failed!!\n")); 2627 pCpu->rc = VERR_DIS_MEM_READ; 2628 } 2629 2630 /** @todo change this into reading directly into abInstr and use it as a 2631 * cache. */ 2632 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->opsize == uAddress 2633 && pCpu->opsize + sizeof(bTemp) < sizeof(pCpu->abInstr))) 2634 pCpu->abInstr[pCpu->opsize++] = bTemp; 2635 else 2636 disStoreInstrBytesSlow(pCpu, uAddress, &bTemp, sizeof(bTemp)); 2637 2638 return bTemp; 2639 } 2640 //***************************************************************************** 2641 //***************************************************************************** 2642 uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress) 2643 { 2644 RTUINT16U uTemp; 2645 uTemp.u = 0; 2646 int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp)); 2647 if (RT_FAILURE(rc)) 2648 { 2649 Log(("DISReadWord failed!!\n")); 2650 pCpu->rc = VERR_DIS_MEM_READ; 2651 } 2652 2653 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->opsize == uAddress 2654 && pCpu->opsize + sizeof(uTemp) < sizeof(pCpu->abInstr))) 2655 { 2656 pCpu->abInstr[pCpu->opsize ] = uTemp.au8[0]; 2657 pCpu->abInstr[pCpu->opsize + 1] = uTemp.au8[1]; 2658 pCpu->opsize += 2; 2659 } 2660 else 2661 disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp)); 2662 2663 return uTemp.u; 2664 } 2665 //***************************************************************************** 2666 //***************************************************************************** 2667 uint32_t DISReadDWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress) 2668 { 2669 RTUINT32U uTemp; 2670 uTemp.u = 0; 2671 int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp)); 2672 if (RT_FAILURE(rc)) 2673 { 2674 Log(("DISReadDWord failed!!\n")); 2675 pCpu->rc = VERR_DIS_MEM_READ; 2676 } 2677 2678 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->opsize == uAddress 2679 && pCpu->opsize + sizeof(uTemp) < sizeof(pCpu->abInstr))) 2680 { 2681 pCpu->abInstr[pCpu->opsize ] = uTemp.au8[0]; 2682 pCpu->abInstr[pCpu->opsize + 1] = uTemp.au8[1]; 2683 pCpu->abInstr[pCpu->opsize + 2] = uTemp.au8[2]; 2684 pCpu->abInstr[pCpu->opsize + 3] = uTemp.au8[3]; 2685 pCpu->opsize += 4; 2686 } 2687 else 2688 disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp)); 2689 2690 return uTemp.u; 2691 } 2692 //***************************************************************************** 2693 //***************************************************************************** 2694 uint64_t DISReadQWord(PDISCPUSTATE pCpu, RTUINTPTR uAddress) 2695 { 2696 RTUINT64U uTemp; 2697 uTemp.u = 0; 2698 int rc = pCpu->pfnReadBytes(pCpu, uTemp.au8, uAddress, sizeof(uTemp)); 2699 if (RT_FAILURE(rc)) 2700 { 2701 Log(("DISReadQWord %x failed!!\n", uAddress)); 2702 pCpu->rc = VERR_DIS_MEM_READ; 2703 } 2704 2705 if (RT_LIKELY( pCpu->uInstrAddr + pCpu->opsize == uAddress 2706 && pCpu->opsize + sizeof(uTemp) < sizeof(pCpu->abInstr))) 2707 { 2708 pCpu->abInstr[pCpu->opsize ] = uTemp.au8[0]; 2709 pCpu->abInstr[pCpu->opsize + 1] = uTemp.au8[1]; 2710 pCpu->abInstr[pCpu->opsize + 2] = uTemp.au8[2]; 2711 pCpu->abInstr[pCpu->opsize + 3] = uTemp.au8[3]; 2712 pCpu->abInstr[pCpu->opsize + 4] = uTemp.au8[4]; 2713 pCpu->abInstr[pCpu->opsize + 5] = uTemp.au8[5]; 2714 pCpu->abInstr[pCpu->opsize + 6] = uTemp.au8[6]; 2715 pCpu->abInstr[pCpu->opsize + 7] = uTemp.au8[7]; 2716 pCpu->opsize += 4; 2717 } 2718 else 2719 disStoreInstrBytesSlow(pCpu, uAddress, uTemp.au8, sizeof(uTemp)); 2720 2721 return uTemp.u; 2709 2722 } 2710 2723 -
trunk/src/VBox/Disassembler/DisasmFormatBytes.cpp
r28800 r41658 5 5 6 6 /* 7 * Copyright (C) 2008 Oracle Corporation7 * Copyright (C) 2008-2012 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 38 38 size_t disFormatBytes(PCDISCPUSTATE pCpu, char *pszDst, size_t cchDst, uint32_t fFlags) 39 39 { 40 /* 41 * Read the bytes first. 42 */ 43 uint8_t ab[16]; 44 uint32_t cb = pCpu->opsize; 45 Assert(cb <= 16); 46 if (cb > 16) 47 cb = 16; 40 size_t cchOutput = 0; 41 uint32_t cb = pCpu->opsize; 42 AssertStmt(cb <= 16, cb = 16); 48 43 49 if (pCpu->pfnReadBytes)50 {51 int rc = pCpu->pfnReadBytes(pCpu->opaddr, &ab[0], cb, (void *)pCpu);52 if (RT_FAILURE(rc))53 {54 for (uint32_t i = 0; i < cb; i++)55 {56 int rc2 = pCpu->pfnReadBytes(pCpu->opaddr + i, &ab[i], 1, (void *)pCpu);57 if (RT_FAILURE(rc2))58 ab[i] = 0xcc;59 }60 }61 }62 else63 {64 uint8_t const *pabSrc = (uint8_t const *)(uintptr_t)pCpu->opaddr;65 for (uint32_t i = 0; i < cb; i++)66 ab[i] = pabSrc[i];67 }68 69 /*70 * Now for the output.71 */72 size_t cchOutput = 0;73 44 #define PUT_C(ch) \ 74 45 do { \ … … 98 69 { 99 70 if (i != 0 && (fFlags & DIS_FMT_FLAGS_BYTES_SPACED)) 100 PUT_NUM(3, " %02x", ab[i]);71 PUT_NUM(3, " %02x", pCpu->abInstr[i]); 101 72 else 102 PUT_NUM(2, "%02x", ab[i]);73 PUT_NUM(2, "%02x", pCpu->abInstr[i]); 103 74 } 104 75 -
trunk/src/VBox/Disassembler/DisasmFormatYasm.cpp
r41505 r41658 689 689 PUT_SZ("word "); 690 690 else if ( (pParam->flags & USE_DISPLACEMENT32) 691 && (int 8_t)pParam->disp32 == (int32_t)pParam->disp32)691 && (int16_t)pParam->disp32 == (int32_t)pParam->disp32) //?? 692 692 PUT_SZ("dword "); 693 693 else if ( (pParam->flags & USE_DISPLACEMENT64) 694 && (int8_t)pParam->disp64 == (int64_t)pParam->disp32) 694 && (pCpu->SIB.Bits.Base != 5 || pCpu->ModRM.Bits.Mod != 0) 695 && (int32_t)pParam->disp64 == (int64_t)pParam->disp64) //?? 695 696 PUT_SZ("qword "); 696 697 } … … 1231 1232 { 1232 1233 uint32_t f; 1233 switch ( DISReadByte(pCpu, offOpcode + pCpu->opaddr))1234 switch (pCpu->abInstr[offOpcode]) 1234 1235 { 1235 1236 case 0xf0: -
trunk/src/VBox/Disassembler/DisasmInternal.h
r40577 r41658 70 70 #define IDX_ParseImmAddrF 40 71 71 #define IDX_ParseMax (IDX_ParseImmAddrF+1) 72 73 #if defined(IN_RING0) || defined(IN_RC)74 #define DIS_THROW(a) /* Not available. */75 #elif __L4ENV__76 #define DIS_THROW(a) longjmp(*pCpu->pJumpBuffer, a)77 #else78 #define DIS_THROW(a) throw(a)79 #endif80 72 81 73 … … 161 153 162 154 /* Read functions */ 155 DECLCALLBACK(int) disReadBytesDefault(PDISCPUSTATE pCpu, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead); 163 156 uint8_t DISReadByte(PDISCPUSTATE pCpu, RTUINTPTR pAddress); 164 157 uint16_t DISReadWord(PDISCPUSTATE pCpu, RTUINTPTR pAddress); -
trunk/src/VBox/Disassembler/DisasmTest.cpp
r28800 r41658 48 48 unsigned cb; 49 49 DISCPUSTATE cpu; 50 char 50 char szOutput[256]; 51 51 52 memset(&cpu, 0, sizeof(cpu)); 53 cpu.mode = CPUMODE_32BIT; 54 if (RT_SUCCESS(DISInstr(&cpu, pInstr, 0, &cb, szOutput))) 52 if (RT_SUCCESS(DISInstr(pInstr, CPUMODE_32BIT, &cpu, &cb, szOutput))) 55 53 { 56 54 printf("%s", szOutput); … … 73 71 unsigned cb; 74 72 DISCPUSTATE cpu; 75 char 73 char szOutput[256]; 76 74 77 memset(&cpu, 0, sizeof(cpu)); 78 cpu.mode = CPUMODE_64BIT; 79 if (RT_SUCCESS(DISInstr(&cpu, pInstr, 0, &cb, szOutput))) 75 if (RT_SUCCESS(DISInstr(pInstr, CPUMODE_64BIT, &cpu, &cb, szOutput))) 80 76 printf("%s", szOutput); 81 77 else -
trunk/src/VBox/Disassembler/DisasmTestCore.cpp
r28800 r41658 39 39 unsigned cb; 40 40 DISCPUSTATE cpu; 41 cpu.mode = CPUMODE_32BIT; 42 if (DISCoreOne(&cpu, (uintptr_t)&DISCoreOne, &cb)) 41 if (DISCoreOneEx((uintptr_t)&DISCoreOneEx, CPUMODE_32BIT, NULL /*pfnReadBytes*/, NULL /*pvUser*/, &cpu, &cb)) 43 42 printf("ok %d\n", cpu.addrmode); 44 43 else -
trunk/src/VBox/Disassembler/testcase/Makefile.kmk
r41477 r41658 60 60 # $(PATH_STAGE_BIN)/testcase/tstDisasm-2$(SUFF_EXEC) 61 61 endif 62 VBOX_DISAS_TESTS_BINARIES_NOT_16BIT := \ 63 tstBinFnstsw-1.bin 64 VBOX_DISAS_TESTS_BINARIES_NOT_32BIT := 65 VBOX_DISAS_TESTS_BINARIES_NOT_64BIT := 62 66 63 67 … … 195 199 196 200 ## @todo 64-bit is problematic because of bugs like POP RDI ending up as POP EDI (incorrect default opmode). 197 #$(foreach bits, 32 16 64, $(foreach binary, $(VBOX_DISAS_TESTS_BINARIES), $(evalvalctx def_vbox_disas_binary))) 198 $(foreach bits, 32 16, $(foreach binary, $(VBOX_DISAS_TESTS_BINARIES), $(evalvalctx def_vbox_disas_binary))) 201 #$(foreach bits, 64, $(foreach binary, $(VBOX_DISAS_TESTS_BINARIES), $(evalvalctx def_vbox_disas_binary))) 202 $(foreach bits, 32 16, $(foreach binary, $(filter-out $(VBOX_DISAS_TESTS_BINARIES_NOT_$(bits)BIT), $(VBOX_DISAS_TESTS_BINARIES)) \ 203 , $(evalvalctx def_vbox_disas_binary))) 199 204 200 205 -
trunk/src/VBox/Disassembler/testcase/tstDisasm-2.cpp
r41501 r41658 171 171 * however the current doesn't do this and is just complicated... 172 172 */ 173 static DECLCALLBACK(int) MyDisasInstrRead( RTUINTPTR uSrcAddr, uint8_t *pbDst, uint32_t cbRead, void *pvDisCpu)174 { 175 PMYDISSTATE pState = (PMYDISSTATE)p vDisCpu;173 static DECLCALLBACK(int) MyDisasInstrRead(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead) 174 { 175 PMYDISSTATE pState = (PMYDISSTATE)pDisState; 176 176 if (RT_LIKELY( pState->uNextAddr == uSrcAddr 177 && pState->cbLeft >= cb Read))177 && pState->cbLeft >= cbToRead)) 178 178 { 179 179 /* 180 180 * Straight forward reading. 181 181 */ 182 if (cb Read == 1)182 if (cbToRead == 1) 183 183 { 184 184 pState->cbLeft--; … … 188 188 else 189 189 { 190 memcpy(pbDst, pState->pbNext, cb Read);191 pState->pbNext += cb Read;192 pState->cbLeft -= cb Read;193 pState->uNextAddr += cb Read;190 memcpy(pbDst, pState->pbNext, cbToRead); 191 pState->pbNext += cbToRead; 192 pState->cbLeft -= cbToRead; 193 pState->uNextAddr += cbToRead; 194 194 } 195 195 } … … 211 211 pState->cbLeft = 0; 212 212 213 memset(pbDst, 0xcc, cb Read);213 memset(pbDst, 0xcc, cbToRead); 214 214 pState->rc = VERR_EOF; 215 215 return VERR_EOF; … … 227 227 228 228 /* do the reading. */ 229 if (pState->cbLeft >= cb Read)230 { 231 memcpy(pbDst, pState->pbNext, cb Read);232 pState->cbLeft -= cb Read;233 pState->pbNext += cb Read;234 pState->uNextAddr += cb Read;229 if (pState->cbLeft >= cbToRead) 230 { 231 memcpy(pbDst, pState->pbNext, cbToRead); 232 pState->cbLeft -= cbToRead; 233 pState->pbNext += cbToRead; 234 pState->uNextAddr += cbToRead; 235 235 } 236 236 else … … 240 240 memcpy(pbDst, pState->pbNext, pState->cbLeft); 241 241 pbDst += pState->cbLeft; 242 cb Read -= (uint32_t)pState->cbLeft;242 cbToRead -= (uint32_t)pState->cbLeft; 243 243 pState->pbNext += pState->cbLeft; 244 244 pState->uNextAddr += pState->cbLeft; 245 245 pState->cbLeft = 0; 246 246 } 247 memset(pbDst, 0xcc, cb Read);247 memset(pbDst, 0xcc, cbToRead); 248 248 pState->rc = VERR_EOF; 249 249 return VERR_EOF; … … 253 253 { 254 254 RTStrmPrintf(g_pStdErr, "Reading before current instruction!\n"); 255 memset(pbDst, 0x90, cb Read);255 memset(pbDst, 0x90, cbToRead); 256 256 pState->rc = VERR_INTERNAL_ERROR; 257 257 return VERR_INTERNAL_ERROR; … … 286 286 */ 287 287 MYDISSTATE State; 288 State.Cpu.mode = enmCpuMode;289 State.Cpu.pfnReadBytes = MyDisasInstrRead;290 288 State.uAddress = uAddress; 291 289 State.pbInstr = pbFile; … … 331 329 State.pbNext = State.pbInstr; 332 330 333 int rc = DISInstr(&State.Cpu, State.uAddress, 0, &State.cbInstr, State.szLine); 331 332 int rc = DISInstrWithReader(State.uAddress, enmCpuMode, MyDisasInstrRead, &State, 333 &State.Cpu, &State.cbInstr, State.szLine); 334 334 if ( RT_SUCCESS(rc) 335 335 || ( ( rc == VERR_DIS_INVALID_OPCODE … … 345 345 if (State.fUndefOp && State.enmUndefOp == kUndefOp_DefineByte) 346 346 { 347 if (!State.cbInstr) 348 { 349 State.Cpu.abInstr[0] = 0; 350 State.Cpu.pfnReadBytes(&State.Cpu, &State.Cpu.abInstr[0], State.uAddress, 1); 351 State.cbInstr = 1; 352 } 347 353 RTPrintf(" db"); 348 if (!State.cbInstr)349 State.cbInstr = 1;350 354 for (unsigned off = 0; off < State.cbInstr; off++) 351 { 352 uint8_t b; 353 State.Cpu.pfnReadBytes(State.uAddress + off, &b, 1, &State.Cpu); 354 RTPrintf(off ? ", %03xh" : " %03xh", b); 355 } 355 RTPrintf(off ? ", %03xh" : " %03xh", State.Cpu.abInstr[off]); 356 356 RTPrintf(" ; %s\n", State.szLine); 357 357 } … … 376 376 RTPrintf(" db"); 377 377 for (unsigned off = 0; off < State.cbInstr; off++) 378 { 379 uint8_t b; 380 State.Cpu.pfnReadBytes(State.uAddress + off, &b, 1, &State.Cpu); 381 RTPrintf(off ? ", %03xh" : " %03xh", b); 382 } 378 RTPrintf(off ? ", %03xh" : " %03xh", State.Cpu.abInstr[off]); 383 379 RTPrintf(" ; "); 384 380 } -
trunk/src/VBox/Runtime/testcase/tstLdr-2.cpp
r38636 r41658 46 46 char szOutput[256]; 47 47 uint32_t cbInstr; 48 if (RT_FAILURE(DISInstr (pCpu, pvCodeBlock + i, off, &cbInstr, szOutput)))48 if (RT_FAILURE(DISInstrWithOff(pCpu, pvCodeBlock + i, off, &cbInstr, szOutput))) 49 49 return false; 50 50 -
trunk/src/VBox/Runtime/testcase/tstLdr-3.cpp
r41078 r41658 144 144 145 145 146 static DECLCALLBACK(int) MyReadBytes(RTUINTPTR uSrc, uint8_t *pbDst, unsigned cb, void *pvUser) 147 { 148 PDISCPUSTATE pCpu = (PDISCPUSTATE)pvUser; 149 memcpy(pbDst, (uint8_t const *)((uintptr_t)uSrc + (uintptr_t)pCpu->apvUserData[0]), cb); 146 /** 147 * @callback_method_impl{FNDISREADBYTES} 148 */ 149 static DECLCALLBACK(int) MyReadBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead) 150 { 151 memcpy(pbDst, (uint8_t const *)((uintptr_t)uSrcAddr + (uintptr_t)pDisState->apvUserData[0]), cbToRead); 150 152 return VINF_SUCCESS; 151 153 } -
trunk/src/VBox/Runtime/testcase/tstLdrDisasmTest.cpp
r39083 r41658 80 80 81 81 82 DECLCALLBACK(int) DisasmTest1ReadCode(RTUINTPTR SrcAddr, uint8_t *pbDst, uint32_t cb, void *pvUser) 82 /** 83 * @callback_method_impl{FNDISREADBYTES} 84 */ 85 static DECLCALLBACK(int) DisasmTest1ReadCode(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead) 83 86 { 84 NOREF(p vUser);85 while (cb > 0)87 NOREF(pDisState); 88 while (cbToRead > 0) 86 89 { 87 *pbDst = g_ab32BitCode[SrcAddr]; 90 *pbDst = g_ab32BitCode[uSrcAddr]; 91 88 92 /* next */ 89 93 pbDst++; 90 SrcAddr++;91 cb --;94 uSrcAddr++; 95 cbToRead--; 92 96 } 93 97 return 0; -
trunk/src/VBox/Runtime/testcase/tstLdrObj.cpp
r39083 r41658 98 98 static unsigned cb; 99 99 DISCPUSTATE Cpu; 100 memset(&Cpu, 0, sizeof(Cpu)); 101 Cpu.mode = CPUMODE_32BIT; 102 DISCoreOne(&Cpu, (uintptr_t)SomeExportFunction3, &cb); 100 DISCoreOneEx((uintptr_t)SomeExportFunction3, CPUMODE_32BIT, NULL /*pfnReadBytes*/, NULL /*pvUser*/, &Cpu, &cb); 103 101 return (void *)(uintptr_t)&SomeExportFunction1; 104 102 } -
trunk/src/VBox/Runtime/testcase/tstLdrObjR0.cpp
r39083 r41658 98 98 Cpu.mode = CPUMODE_32BIT; 99 99 100 DISCoreOne (&Cpu, (uintptr_t)SomeExportFunction3, &cb);100 DISCoreOneEx((uintptr_t)SomeExportFunction3, CPUMODE_32BIT, NULL /*pfnReadBytes*/, NULL /*pvUser*/, &Cpu, &cb); 101 101 return (void *)(uintptr_t)&SomeExportFunction1; 102 102 } -
trunk/src/VBox/VMM/VMMAll/EMAll.cpp
r41072 r41658 5 5 6 6 /* 7 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2012 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 282 282 283 283 /** 284 * Read callback for disassembly function; supports reading bytes that cross a page boundary 285 * 286 * @returns VBox status code. 287 * @param pSrc GC source pointer 288 * @param pDest HC destination pointer 289 * @param cb Number of bytes to read 290 * @param dwUserdata Callback specific user data (pDis) 291 * 292 */ 293 static DECLCALLBACK(int) emReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned cb, void *pvUserdata) 294 { 295 PDISCPUSTATE pDis = (PDISCPUSTATE)pvUserdata; 296 PEMDISSTATE pState = (PEMDISSTATE)pDis->apvUserData[0]; 284 * @callback_method_impl{FNDISREADBYTES} 285 */ 286 static DECLCALLBACK(int) emReadBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead) 287 { 288 PEMDISSTATE pState = (PEMDISSTATE)pDisState->apvUserData[0]; 297 289 # ifndef IN_RING0 298 290 PVM pVM = pState->pVM; … … 304 296 305 297 if ( pState->GCPtr 306 && pSrc + cb<= pState->GCPtr + sizeof(pState->aOpcode))307 { 308 unsigned offset = pSrc- pState->GCPtr;309 Assert( pSrc>= pState->GCPtr);310 311 for (unsigned i = 0; i < cb ; i++)312 p Dest[i] = pState->aOpcode[offset + i];298 && uSrcAddr + cbToRead <= pState->GCPtr + sizeof(pState->aOpcode)) 299 { 300 unsigned offset = uSrcAddr - pState->GCPtr; 301 Assert(uSrcAddr >= pState->GCPtr); 302 303 for (unsigned i = 0; i < cbToRead; i++) 304 pbDst[i] = pState->aOpcode[offset + i]; 313 305 return VINF_SUCCESS; 314 306 } 315 307 316 rc = PGMPhysSimpleReadGCPtr(pVCpu, p Dest, pSrc, cb);317 AssertMsgRC(rc, ("PGMPhysSimpleReadGCPtr failed for pSrc=%RGv cb=%x rc=%d\n", pSrc, cb, rc));308 rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead); 309 AssertMsgRC(rc, ("PGMPhysSimpleReadGCPtr failed for uSrcAddr=%RTptr cbToRead=%x rc=%d\n", uSrcAddr, cbToRead, rc)); 318 310 # elif defined(IN_RING3) 319 if (!PATMIsPatchGCAddr(pVM, pSrc))320 { 321 int rc = PGMPhysSimpleReadGCPtr(pVCpu, p Dest, pSrc, cb);311 if (!PATMIsPatchGCAddr(pVM, uSrcAddr)) 312 { 313 int rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead); 322 314 AssertRC(rc); 323 315 } 324 316 else 325 memcpy(p Dest, PATMR3GCPtrToHCPtr(pVM, pSrc), cb);317 memcpy(pbDst, PATMR3GCPtrToHCPtr(pVM, uSrcAddr), cbToRead); 326 318 327 319 # elif defined(IN_RC) 328 if (!PATMIsPatchGCAddr(pVM, pSrc))329 { 330 int rc = MMGCRamRead(pVM, p Dest, (void *)(uintptr_t)pSrc, cb);320 if (!PATMIsPatchGCAddr(pVM, uSrcAddr)) 321 { 322 int rc = MMGCRamRead(pVM, pbDst, (void *)(uintptr_t)uSrcAddr, cbToRead); 331 323 if (rc == VERR_ACCESS_DENIED) 332 324 { 333 325 /* Recently flushed; access the data manually. */ 334 rc = PGMPhysSimpleReadGCPtr(pVCpu, p Dest, pSrc, cb);326 rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead); 335 327 AssertRC(rc); 336 328 } 337 329 } 338 330 else /* the hypervisor region is always present. */ 339 memcpy(p Dest, (RTRCPTR)(uintptr_t)pSrc, cb);331 memcpy(pbDst, (RTRCPTR)(uintptr_t)uSrcAddr, cbToRead); 340 332 341 333 # endif /* IN_RING3 */ … … 343 335 } 344 336 345 346 337 #ifndef IN_RC 338 347 339 DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, RTGCUINTPTR InstrGC, uint32_t *pOpsize) 348 340 { … … 467 459 #endif 468 460 469 rc = DISCoreOneEx(GCPtrInstr, SELMGetCpuModeFromSelector(pVCpu, pCtxCore->eflags, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid), 461 rc = DISCoreOneEx(GCPtrInstr, 462 SELMGetCpuModeFromSelector(pVCpu, pCtxCore->eflags, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid), 470 463 emReadBytes, &State, 471 464 pDis, pcbInstr); … … 659 652 Assert(!CPUMIsGuestIn64BitCode(pVCpu, pRegFrame)); 660 653 /** @todo Rainy day: Test what happens when VERR_EM_INTERPRETER is returned by 661 * this function. F airethat it may guru on us, thus not converted to654 * this function. Fear that it may guru on us, thus not converted to 662 655 * IEM. */ 663 656 -
trunk/src/VBox/VMM/VMMR3/CPUM.cpp
r41310 r41658 906 906 pCPUM->aGuestCpuIdCentaur[i] = pCPUM->GuestCpuIdDef; 907 907 908 /* 908 /* 909 909 * Hypervisor identification. 910 910 * … … 3525 3525 3526 3526 /** 3527 * Instruction reader. 3528 * 3529 * @returns VBox status code. 3530 * @param PtrSrc Address to read from. 3531 * In our case this is relative to the selector pointed to by the 2nd user argument of uDisCpu. 3532 * @param pu8Dst Where to store the bytes. 3533 * @param cbRead Number of bytes to read. 3534 * @param uDisCpu Pointer to the disassembler cpu state. 3535 * In this context it's always pointer to the Core of a DBGFDISASSTATE. 3536 */ 3537 static DECLCALLBACK(int) cpumR3DisasInstrRead(RTUINTPTR PtrSrc, uint8_t *pu8Dst, unsigned cbRead, void *uDisCpu) 3538 { 3539 PDISCPUSTATE pCpu = (PDISCPUSTATE)uDisCpu; 3540 PCPUMDISASSTATE pState = (PCPUMDISASSTATE)pCpu->apvUserData[0]; 3541 Assert(cbRead > 0); 3527 * @callback_method_impl{FNDISREADBYTES} 3528 */ 3529 static DECLCALLBACK(int) cpumR3DisasInstrRead(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead) 3530 { 3531 PCPUMDISASSTATE pState = (PCPUMDISASSTATE)pDisState->apvUserData[0]; 3532 Assert(cbToRead > 0); 3542 3533 for (;;) 3543 3534 { 3544 RTGCUINTPTR GCPtr = PtrSrc+ pState->GCPtrSegBase;3535 RTGCUINTPTR GCPtr = uSrcAddr + pState->GCPtrSegBase; 3545 3536 3546 3537 /* Need to update the page translation? */ … … 3575 3566 3576 3567 /* check the segment limit */ 3577 if (!pState->f64Bits && PtrSrc> pState->cbSegLimit)3568 if (!pState->f64Bits && uSrcAddr > pState->cbSegLimit) 3578 3569 return VERR_OUT_OF_SELECTOR_BOUNDS; 3579 3570 … … 3586 3577 cb = cbSeg; 3587 3578 } 3588 if (cb > cb Read)3589 cb = cb Read;3579 if (cb > cbToRead) 3580 cb = cbToRead; 3590 3581 3591 3582 /* read and advance */ 3592 memcpy(p u8Dst, (char *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb);3593 cb Read -= cb;3594 if (!cb Read)3583 memcpy(pbDst, (char *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb); 3584 cbToRead -= cb; 3585 if (!cbToRead) 3595 3586 return VINF_SUCCESS; 3596 p u8Dst+= cb;3597 PtrSrc+= cb;3587 pbDst += cb; 3588 uSrcAddr += cb; 3598 3589 } 3599 3590 } … … 3629 3620 * Get selector information. 3630 3621 */ 3622 DISCPUMODE enmDisCpuMode; 3631 3623 if ( (pCtx->cr0 & X86_CR0_PE) 3632 3624 && pCtx->eflags.Bits.u1VM == 0) … … 3638 3630 State.GCPtrSegEnd = pCtx->csHid.u32Limit + 1 + (RTGCUINTPTR)pCtx->csHid.u64Base; 3639 3631 State.cbSegLimit = pCtx->csHid.u32Limit; 3640 pCpu->mode= (State.f64Bits)3632 enmDisCpuMode = (State.f64Bits) 3641 3633 ? CPUMODE_64BIT 3642 3634 : pCtx->csHid.Attr.n.u1DefBig … … 3667 3659 State.GCPtrSegEnd = SelInfo.cbLimit + 1 + (RTGCUINTPTR)SelInfo.GCPtrBase; 3668 3660 State.cbSegLimit = SelInfo.cbLimit; 3669 pCpu->mode= SelInfo.u.Raw.Gen.u1DefBig ? CPUMODE_32BIT : CPUMODE_16BIT;3661 enmDisCpuMode = SelInfo.u.Raw.Gen.u1DefBig ? CPUMODE_32BIT : CPUMODE_16BIT; 3670 3662 } 3671 3663 } … … 3673 3665 { 3674 3666 /* real or V86 mode */ 3675 pCpu->mode= CPUMODE_16BIT;3667 enmDisCpuMode = CPUMODE_16BIT; 3676 3668 State.GCPtrSegBase = pCtx->cs * 16; 3677 3669 State.GCPtrSegEnd = 0xFFFFFFFF; … … 3682 3674 * Disassemble the instruction. 3683 3675 */ 3684 pCpu->pfnReadBytes = cpumR3DisasInstrRead;3685 pCpu->apvUserData[0] = &State;3686 3687 3676 uint32_t cbInstr; 3688 3677 #ifndef LOG_ENABLED 3689 rc = DISInstr (pCpu, GCPtrPC, 0, &cbInstr, NULL);3678 rc = DISInstrWithReader(GCPtrPC, enmDisCpuMode, cpumR3DisasInstrRead, &State, pCpu, &cbInstr, NULL); 3690 3679 if (RT_SUCCESS(rc)) 3691 3680 { 3692 3681 #else 3693 3682 char szOutput[160]; 3694 rc = DISInstr (pCpu, GCPtrPC, 0, &cbInstr, &szOutput[0]);3683 rc = DISInstrWithReader(GCPtrPC, enmDisCpuMode, cpumR3DisasInstrRead, &State, pCpu, &cbInstr, szOutput); 3695 3684 if (RT_SUCCESS(rc)) 3696 3685 { -
trunk/src/VBox/VMM/VMMR3/CSAM.cpp
r40449 r41658 724 724 725 725 /** 726 * Read callback for disassembly function; supports reading bytes that cross a page boundary 727 * 728 * @returns VBox status code. 729 * @param pSrc GC source pointer 730 * @param pDest HC destination pointer 731 * @param size Number of bytes to read 732 * @param dwUserdata Callback specific user data (pCpu) 733 * 734 */ 735 static DECLCALLBACK(int) CSAMR3ReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata) 736 { 737 DISCPUSTATE *pCpu = (DISCPUSTATE *)pvUserdata; 738 PVM pVM = (PVM)pCpu->apvUserData[0]; 739 RTHCUINTPTR pInstrHC = (RTHCUINTPTR)pCpu->apvUserData[1]; 740 RTGCUINTPTR32 pInstrGC = (uintptr_t)pCpu->apvUserData[2]; 741 int orgsize = size; 742 Assert(pVM->cCpus == 1); 743 PVMCPU pVCpu = VMMGetCpu0(pVM); 744 745 /* We are not interested in patched instructions, so read the original opcode bytes. */ 746 /** @note single instruction patches (int3) are checked in CSAMR3AnalyseCallback */ 747 for (int i=0;i<orgsize;i++) 748 { 749 int rc = PATMR3QueryOpcode(pVM, (RTRCPTR)pSrc, pDest); 750 if (RT_SUCCESS(rc)) 751 { 752 pSrc++; 753 pDest++; 754 size--; 755 } 756 else 726 * @callback_method_impl{FNDISREADBYTES} 727 */ 728 static DECLCALLBACK(int) CSAMR3ReadBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead) 729 { 730 PVM pVM = (PVM)pDisState->apvUserData[0]; 731 RTHCUINTPTR pInstrHC = (RTHCUINTPTR)pDisState->apvUserData[1]; 732 RTGCUINTPTR32 pInstrGC = pDisState->uInstrAddr; 733 int orgsize = cbToRead; 734 PVMCPU pVCpu = VMMGetCpu0(pVM); 735 736 /* We are not interested in patched instructions, so read the original opcode bytes. 737 Note! single instruction patches (int3) are checked in CSAMR3AnalyseCallback */ 738 for (int i = 0; i < orgsize; i++) 739 { 740 int rc = PATMR3QueryOpcode(pVM, (RTRCPTR)uSrcAddr, pbDst); 741 if (RT_FAILURE(rc)) 757 742 break; 758 } 759 if (size == 0) 743 uSrcAddr++; 744 pbDst++; 745 cbToRead--; 746 } 747 if (cbToRead == 0) 760 748 return VINF_SUCCESS; 761 749 762 if (PAGE_ADDRESS(pInstrGC) != PAGE_ADDRESS(pSrc + size - 1) && !PATMIsPatchGCAddr(pVM, pSrc)) 763 { 764 return PGMPhysSimpleReadGCPtr(pVCpu, pDest, pSrc, size); 765 } 766 else 767 { 768 Assert(pInstrHC); 769 770 /* pInstrHC is the base address; adjust according to the GC pointer. */ 771 pInstrHC = pInstrHC + (pSrc - pInstrGC); 772 773 memcpy(pDest, (void *)pInstrHC, size); 774 } 750 if (PAGE_ADDRESS(pInstrGC) != PAGE_ADDRESS(uSrcAddr + cbToRead - 1) && !PATMIsPatchGCAddr(pVM, uSrcAddr)) 751 return PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead); 752 753 Assert(pInstrHC); 754 755 /* pInstrHC is the base address; adjust according to the GC pointer. */ 756 pInstrHC = pInstrHC + (uSrcAddr - pInstrGC); 757 758 memcpy(pbDst, (void *)pInstrHC, cbToRead); 775 759 776 760 return VINF_SUCCESS; 777 761 } 778 762 779 inline int CSAMR3DISInstr(PVM pVM, DISCPUSTATE *pCpu, RTRCPTR InstrGC, uint8_t *InstrHC, uint32_t *pOpsize, char *pszOutput) 780 { 781 (pCpu)->pfnReadBytes = CSAMR3ReadBytes; 782 (pCpu)->apvUserData[0] = pVM; 763 DECLINLINE(int) CSAMR3DISInstr(PVM pVM, RTRCPTR InstrGC, uint8_t *InstrHC, DISCPUMODE enmCpuMode, 764 PDISCPUSTATE pCpu, uint32_t *pcbInstr, char *pszOutput) 765 { 783 766 (pCpu)->apvUserData[1] = InstrHC; 784 767 (pCpu)->apvUserData[2] = (void *)(uintptr_t)InstrGC; Assert(sizeof(InstrGC) <= sizeof(pCpu->apvUserData[0])); 785 768 #ifdef DEBUG 786 return DISInstrEx(pCpu, InstrGC, 0, pOpsize, pszOutput, OPTYPE_ALL); 769 return DISInstrEx(InstrGC, 0, enmCpuMode, CSAMR3ReadBytes, pVM, OPTYPE_ALL, 770 pCpu, pcbInstr, pszOutput); 787 771 #else 788 772 /* We are interested in everything except harmless stuff */ 789 return DISInstrEx(pCpu, InstrGC, 0, pOpsize, pszOutput, ~(OPTYPE_INVALID | OPTYPE_HARMLESS | OPTYPE_RRM_MASK)); 773 return DISInstrEx(InstrGC, 0, enmCpuMode, CSAMR3ReadBytes, pVM, ~(OPTYPE_INVALID | OPTYPE_HARMLESS | OPTYPE_RRM_MASK), 774 pCpu, pcbInstr, pszOutput); 790 775 #endif 791 776 } … … 883 868 Assert(VALID_PTR(pCurInstrHC)); 884 869 885 cpu.mode = (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT;886 rc = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, &opsize, NULL);870 rc = CSAMR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT, 871 &cpu, &opsize, NULL); 887 872 } 888 873 AssertRC(rc); … … 1054 1039 * - push ebp after the filler (can extend this later); aligned at at least a 4 byte boundary 1055 1040 */ 1056 for (int j =0;j<16;j++)1041 for (int j = 0; j < 16; j++) 1057 1042 { 1058 1043 uint8_t *pCurInstrHC = (uint8_t *)CSAMGCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC); … … 1064 1049 Assert(VALID_PTR(pCurInstrHC)); 1065 1050 1066 cpu.mode = (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT;1067 1051 STAM_PROFILE_START(&pVM->csam.s.StatTimeDisasm, a); 1068 1052 #ifdef DEBUG 1069 rc2 = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, &opsize, szOutput); 1053 rc2 = CSAMR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT, 1054 &cpu, &opsize, szOutput); 1070 1055 if (RT_SUCCESS(rc2)) Log(("CSAM Call Analysis: %s", szOutput)); 1071 1056 #else 1072 rc2 = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, &opsize, NULL); 1057 rc2 = CSAMR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT, 1058 &cpu, &opsize, NULL); 1073 1059 #endif 1074 1060 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeDisasm, a); … … 1276 1262 Assert(VALID_PTR(pCurInstrHC)); 1277 1263 1278 cpu.mode = (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT;1279 1264 STAM_PROFILE_START(&pVM->csam.s.StatTimeDisasm, a); 1280 1265 #ifdef DEBUG 1281 rc2 = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, &opsize, szOutput); 1266 rc2 = CSAMR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT, 1267 &cpu, &opsize, szOutput); 1282 1268 if (RT_SUCCESS(rc2)) Log(("CSAM Analysis: %s", szOutput)); 1283 1269 #else 1284 rc2 = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, &opsize, NULL); 1270 rc2 = CSAMR3DISInstr(pVM, &cpu, pCurInstrGC, pCurInstrHC, (fCode32) ? CPUMODE_32BIT : CPUMODE_16BIT, 1271 &cpu, &opsize, NULL); 1285 1272 #endif 1286 1273 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeDisasm, a); -
trunk/src/VBox/VMM/VMMR3/DBGFDisas.cpp
r38838 r41658 82 82 * Internal Functions * 83 83 *******************************************************************************/ 84 static DECLCALLBACK(int) dbgfR3DisasInstrRead(RTUINTPTR pSrc, uint8_t *pDest, uint32_t size, void *pvUserdata);84 static FNDISREADBYTES dbgfR3DisasInstrRead; 85 85 86 86 … … 199 199 200 200 /** 201 * Instruction reader. 202 * 203 * @returns VBox status code. (Why this is a int32_t and not just an int is also beyond me.) 204 * @param PtrSrc Address to read from. 205 * In our case this is relative to the selector pointed to by the 2nd user argument of uDisCpu. 206 * @param pu8Dst Where to store the bytes. 207 * @param cbRead Number of bytes to read. 208 * @param uDisCpu Pointer to the disassembler cpu state. (Why this is a VBOXHUINTPTR is beyond me...) 209 * In this context it's always pointer to the Core of a DBGFDISASSTATE. 210 */ 211 static DECLCALLBACK(int) dbgfR3DisasInstrRead(RTUINTPTR PtrSrc, uint8_t *pu8Dst, uint32_t cbRead, void *pvDisCpu) 212 { 213 PDBGFDISASSTATE pState = (PDBGFDISASSTATE)pvDisCpu; 214 Assert(cbRead > 0); 201 * @callback_method_impl{FNDISREADBYTES} 202 * 203 * @remarks @a uSrcAddr is relative to the base address indicated by 204 * DBGFDISASSTATE::GCPtrSegBase. 205 */ 206 static DECLCALLBACK(int) dbgfR3DisasInstrRead(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead) 207 { 208 PDBGFDISASSTATE pState = (PDBGFDISASSTATE)pDisState; 209 Assert(cbToRead > 0); 215 210 for (;;) 216 211 { 217 RTGCUINTPTR GCPtr = PtrSrc+ pState->GCPtrSegBase;212 RTGCUINTPTR GCPtr = uSrcAddr + pState->GCPtrSegBase; 218 213 219 214 /* Need to update the page translation? */ … … 250 245 251 246 /* check the segment limit */ 252 if (!pState->f64Bits && PtrSrc> pState->cbSegLimit)247 if (!pState->f64Bits && uSrcAddr > pState->cbSegLimit) 253 248 return VERR_OUT_OF_SELECTOR_BOUNDS; 254 249 … … 261 256 cb = cbSeg; 262 257 } 263 if (cb > cb Read)264 cb = cb Read;258 if (cb > cbToRead) 259 cb = cbToRead; 265 260 266 261 /* read and advance */ 267 memcpy(p u8Dst, (char *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb);268 cb Read -= cb;269 if (!cb Read)262 memcpy(pbDst, (char *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb); 263 cbToRead -= cb; 264 if (!cbToRead) 270 265 return VINF_SUCCESS; 271 p u8Dst+= cb;272 PtrSrc+= cb;266 pbDst += cb; 267 uSrcAddr += cb; 273 268 } 274 269 } … … 507 502 uint32_t cbBits = State.Cpu.opsize; 508 503 uint8_t *pau8Bits = (uint8_t *)alloca(cbBits); 509 rc = dbgfR3DisasInstrRead( GCPtr, pau8Bits, cbBits, &State);504 rc = dbgfR3DisasInstrRead(&State.Cpu, pau8Bits, GCPtr, cbBits); 510 505 AssertRC(rc); 511 506 if (fFlags & DBGF_DISAS_FLAGS_NO_ADDRESS) -
trunk/src/VBox/VMM/VMMR3/PATM.cpp
r39417 r41658 517 517 } 518 518 519 /** 520 * Read callback for disassembly function; supports reading bytes that cross a page boundary 521 * 522 * @returns VBox status code. 523 * @param pSrc GC source pointer 524 * @param pDest HC destination pointer 525 * @param size Number of bytes to read 526 * @param pvUserdata Callback specific user data (pCpu) 527 * 528 */ 529 int patmReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata) 530 { 531 DISCPUSTATE *pCpu = (DISCPUSTATE *)pvUserdata; 532 PATMDISASM *pDisInfo = (PATMDISASM *)pCpu->apvUserData[0]; 533 int orgsize = size; 534 535 Assert(size); 536 if (size == 0) 519 DECLCALLBACK(int) patmReadBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead) 520 { 521 PATMDISASM *pDisInfo = (PATMDISASM *)pDisState->apvUserData[0]; 522 int orgsize = cbToRead; 523 524 Assert(cbToRead); 525 if (cbToRead == 0) 537 526 return VERR_INVALID_PARAMETER; 538 527 … … 544 533 if (pDisInfo->fReadFlags & PATMREAD_ORGCODE) 545 534 { 546 for (int i=0;i<orgsize;i++) 547 { 548 int rc = PATMR3QueryOpcode(pDisInfo->pVM, (RTRCPTR)pSrc, pDest); 549 if (RT_SUCCESS(rc)) 550 { 551 pSrc++; 552 pDest++; 553 size--; 554 } 555 else break; 556 } 557 if (size == 0) 535 for (int i = 0; i < orgsize; i++) 536 { 537 int rc = PATMR3QueryOpcode(pDisInfo->pVM, (RTRCPTR)uSrcAddr, pbDst); 538 if (RT_FAILURE(rc)) 539 break; 540 uSrcAddr++; 541 pbDst++; 542 cbToRead--; 543 } 544 if (cbToRead == 0) 558 545 return VINF_SUCCESS; 559 546 #ifdef VBOX_STRICT … … 561 548 && !(pDisInfo->fReadFlags & PATMREAD_NOCHECK)) 562 549 { 563 Assert(PATMR3IsInsidePatchJump(pDisInfo->pVM, pSrc, NULL) == false);564 Assert(PATMR3IsInsidePatchJump(pDisInfo->pVM, pSrc+size-1, NULL) == false);550 Assert(PATMR3IsInsidePatchJump(pDisInfo->pVM, uSrcAddr, NULL) == false); 551 Assert(PATMR3IsInsidePatchJump(pDisInfo->pVM, uSrcAddr+cbToRead-1, NULL) == false); 565 552 } 566 553 #endif … … 568 555 569 556 if ( !pDisInfo->pInstrHC 570 || ( PAGE_ADDRESS(pDisInfo->pInstrGC) != PAGE_ADDRESS(pSrc + size - 1) 571 && !PATMIsPatchGCAddr(pDisInfo->pVM, pSrc))) 572 { 573 Assert(!PATMIsPatchGCAddr(pDisInfo->pVM, pSrc)); 574 return PGMPhysSimpleReadGCPtr(&pDisInfo->pVM->aCpus[0], pDest, pSrc, size); 575 } 576 else 577 { 578 Assert(pDisInfo->pInstrHC); 579 580 uint8_t *pInstrHC = pDisInfo->pInstrHC; 581 582 Assert(pInstrHC); 583 584 /* pInstrHC is the base address; adjust according to the GC pointer. */ 585 pInstrHC = pInstrHC + (pSrc - pDisInfo->pInstrGC); 586 587 memcpy(pDest, (void *)pInstrHC, size); 588 } 557 || ( PAGE_ADDRESS(pDisInfo->pInstrGC) != PAGE_ADDRESS(uSrcAddr + cbToRead - 1) 558 && !PATMIsPatchGCAddr(pDisInfo->pVM, uSrcAddr))) 559 { 560 Assert(!PATMIsPatchGCAddr(pDisInfo->pVM, uSrcAddr)); 561 return PGMPhysSimpleReadGCPtr(&pDisInfo->pVM->aCpus[0], pbDst, uSrcAddr, cbToRead); 562 } 563 564 Assert(pDisInfo->pInstrHC); 565 566 uint8_t *pInstrHC = pDisInfo->pInstrHC; 567 568 Assert(pInstrHC); 569 570 /* pInstrHC is the base address; adjust according to the GC pointer. */ 571 pInstrHC = pInstrHC + (uSrcAddr - pDisInfo->pInstrGC); 572 573 memcpy(pbDst, (void *)pInstrHC, cbToRead); 589 574 590 575 return VINF_SUCCESS; … … 2837 2822 if (pPatch->flags & PATMFL_INT3_REPLACEMENT_BLOCK) 2838 2823 { 2839 /*uint8_t ASMInt3 = 0xCC; - unused */2824 /*uint8_t bASMInt3 = 0xCC; - unused */ 2840 2825 2841 2826 Log(("PATMR3PatchBlock %RRv -> int 3 callable patch.\n", pPatch->pPrivInstrGC)); … … 3786 3771 static int patmActivateInt3Patch(PVM pVM, PPATCHINFO pPatch) 3787 3772 { 3788 uint8_t ASMInt3 = 0xCC;3773 uint8_t bASMInt3 = 0xCC; 3789 3774 int rc; 3790 3775 … … 3793 3778 3794 3779 /* Replace first opcode byte with 'int 3'. */ 3795 rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pPatch->pPrivInstrGC, & ASMInt3, sizeof(ASMInt3));3780 rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pPatch->pPrivInstrGC, &bASMInt3, sizeof(bASMInt3)); 3796 3781 AssertRC(rc); 3797 3782 3798 pPatch->cbPatchJump = sizeof( ASMInt3);3783 pPatch->cbPatchJump = sizeof(bASMInt3); 3799 3784 3800 3785 return rc; … … 3823 3808 3824 3809 /** 3825 * Replace an instruction with a breakpoint (0xCC), that is handled dynamically in the guest context. 3810 * Replace an instruction with a breakpoint (0xCC), that is handled dynamically 3811 * in the raw-mode context. 3826 3812 * 3827 3813 * @returns VBox status code. … … 3835 3821 * 3836 3822 */ 3837 VMMR3DECL(int) PATMR3PatchInstrInt3(PVM pVM, RTRCPTR pInstrGC, R3PTRTYPE(uint8_t *) pInstrHC, DISCPUSTATE *pCpu, PPATCHINFO pPatch) 3838 { 3839 uint8_t ASMInt3 = 0xCC; 3823 VMMR3DECL(int) PATMR3PatchInstrInt3(PVM pVM, RTRCPTR pInstrGC, R3PTRTYPE(uint8_t *) pInstrHC, DISCPUSTATE *pCpu, 3824 PPATCHINFO pPatch) 3825 { 3826 uint8_t bASMInt3 = 0xCC; 3840 3827 int rc; 3841 3828 … … 3855 3842 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), pPatch->aPrivInstr, pPatch->pPrivInstrGC, pPatch->cbPrivInstr); 3856 3843 AssertRC(rc); 3857 pPatch->cbPatchJump = sizeof( ASMInt3); /* bit of a misnomer in this case; size of replacement instruction. */3844 pPatch->cbPatchJump = sizeof(bASMInt3); /* bit of a misnomer in this case; size of replacement instruction. */ 3858 3845 3859 3846 pPatch->flags |= PATMFL_INT3_REPLACEMENT; -
trunk/src/VBox/VMM/VMMR3/VMMSwitcher.cpp
r39402 r41658 837 837 uint32_t cbInstr = 0; 838 838 char szDisas[256]; 839 if (RT_SUCCESS(DISInstr(&Cpu, (uintptr_t)pu8CodeR3 + offCode, uBase - (uintptr_t)pu8CodeR3, &cbInstr, szDisas))) 839 if (RT_SUCCESS(DISInstrWithOff(&Cpu, (uintptr_t)pu8CodeR3 + offCode, uBase - (uintptr_t)pu8CodeR3, 840 &cbInstr, szDisas))) 840 841 RTLogPrintf(" %04x: %s", offCode, szDisas); //for whatever reason szDisas includes '\n'. 841 842 else -
trunk/src/VBox/VMM/VMMRC/PATMRC.cpp
r40453 r41658 1 1 /* $Id$ */ 2 2 /** @file 3 * PATM - Dynamic Guest OS Patching Manager - Guest Context3 * PATM - Dynamic Guest OS Patching Manager - Raw-mode Context. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2012 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 *******************************************************************************/ 22 22 #define LOG_GROUP LOG_GROUP_PATM 23 #include <VBox/vmm/patm.h> 23 24 #include <VBox/vmm/cpum.h> 24 25 #include <VBox/vmm/stam.h> 25 #include <VBox/vmm/patm.h>26 26 #include <VBox/vmm/pgm.h> 27 27 #include <VBox/vmm/mm.h> 28 #include <VBox/sup.h> 28 #include <VBox/vmm/em.h> 29 #ifdef VBOX_WITH_IEM 30 # include <VBox/vmm/iem.h> 31 #endif 32 #include <VBox/vmm/selm.h> 29 33 #include <VBox/vmm/mm.h> 30 #include <VBox/param.h>31 #include <iprt/avl.h>32 34 #include "PATMInternal.h" 33 35 #include "PATMA.h" … … 36 38 #include <VBox/dis.h> 37 39 #include <VBox/disopcode.h> 38 #include <VBox/vmm/em.h>39 40 #include <VBox/err.h> 40 #include <VBox/vmm/selm.h>41 41 #include <VBox/log.h> 42 42 #include <iprt/assert.h> … … 441 441 * Checks if the int 3 was caused by a patched instruction 442 442 * 443 * @returns VBox status 443 * @returns Strict VBox status, includes all statuses that 444 * EMInterpretInstructionDisasState and 445 * @retval VINF_SUCCESS 446 * @retval VINF_PATM_PATCH_INT3 447 * @retval VINF_EM_RAW_EMULATE_INSTR 444 448 * 445 449 * @param pVM The VM handle. 446 450 * @param pCtxCore The relevant core context. 447 451 */ 448 VMM DECL(int) PATMHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame)452 VMMRCDECL(int) PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame) 449 453 { 450 454 PPATMPATCHREC pRec; … … 456 460 if (PATMIsPatchGCAddr(pVM, pRegFrame->eip)) 457 461 { 458 /* @note hardcoded assumption about it being a single byte int 3 instruction. */462 /* Note! Hardcoded assumption about it being a single byte int 3 instruction. */ 459 463 pRegFrame->eip--; 460 464 return VINF_PATM_PATCH_INT3; … … 512 516 return VINF_EM_RAW_EMULATE_INSTR; 513 517 } 514 rc = DISCoreOne(&cpu, (uintptr_t)&pRec->patch.aPrivInstr[0], &cbOp); 518 519 #ifdef VBOX_WITH_IEM 520 VBOXSTRICTRC rcStrict; 521 rcStrict = IEMExecOneWithOpcodes(VMMGetCpu0(pVM), pRegFrame, pRec->patch.pPrivInstrGC, 522 pRec->patch.aPrivInstr, pRec->patch.cbPrivInstr); 523 rc = VBOXSTRICTRC_TODO(rcStrict); 524 #else 525 rc = DISCoreOneEx((uintptr_t)&pRec->patch.aPrivInstr[0], cpu.mode, NULL /*pfnReadBytes*/, NULL /*pvUser*/, 526 &cpu, &cbOp); 515 527 if (RT_FAILURE(rc)) 516 528 { … … 523 535 rc = EMInterpretInstructionDisasState(VMMGetCpu0(pVM), &cpu, pRegFrame, 0 /* not relevant here */, 524 536 EMCODETYPE_SUPERVISOR); 525 if (rc != VINF_SUCCESS) 537 #endif 538 if (RT_FAILURE(rc)) 526 539 { 527 540 Log(("EMInterpretInstructionCPU failed with %Rrc\n", rc)); … … 530 543 return VINF_EM_RAW_EMULATE_INSTR; 531 544 } 532 return VINF_SUCCESS;545 return rc; 533 546 } 534 547 } -
trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
r40486 r41658 421 421 && !pRegFrame->eflags.Bits.u1VM) 422 422 { 423 rc = PATMHandleInt3PatchTrap(pVM, pRegFrame); 424 if (rc == VINF_SUCCESS || rc == VINF_EM_RAW_EMULATE_INSTR || rc == VINF_PATM_PATCH_INT3 || rc == VINF_PATM_DUPLICATE_FUNCTION) 423 rc = PATMRCHandleInt3PatchTrap(pVM, pRegFrame); 424 if ( rc == VINF_SUCCESS 425 || rc == VINF_EM_RAW_EMULATE_INSTR 426 || rc == VINF_PATM_PATCH_INT3 427 || rc == VINF_PATM_DUPLICATE_FUNCTION) 425 428 { 426 429 rc = trpmGCExitTrap(pVM, pVCpu, rc, pRegFrame); … … 745 748 { 746 749 /* Int 3 replacement patch? */ 747 if (PATM HandleInt3PatchTrap(pVM, pRegFrame) == VINF_SUCCESS)750 if (PATMRCHandleInt3PatchTrap(pVM, pRegFrame) == VINF_SUCCESS) 748 751 { 749 752 AssertFailed(); -
trunk/src/VBox/VMM/include/PATMInternal.h
r36801 r41658 273 273 /** Size of the patch jump in the guest code. */ 274 274 uint32_t cbPatchJump; 275 /* Only valid for PATMFL_JUMP_CONFLICT patches */275 /** Only valid for PATMFL_JUMP_CONFLICT patches */ 276 276 RTRCPTR pPatchJumpDestGC; 277 277 /** Offset of the patch code from the beginning of the patch memory area. */ … … 675 675 676 676 677 /** 678 * Read callback for disassembly function; supports reading bytes that cross a page boundary 679 * 680 * @returns VBox status code. 681 * @param pSrc GC source pointer 682 * @param pDest HC destination pointer 683 * @param size Number of bytes to read 684 * @param pvUserdata Callback specific user data (pCpu) 685 * 686 */ 687 int patmReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata); 677 FNDISREADBYTES patmReadBytes; 688 678 689 679 … … 706 696 } PATMDISASM, *PPATMDISASM; 707 697 708 inline bool PATMR3DISInstr(PVM pVM, PPATCHINFO pPatch, DISCPUSTATE *pCpu, RTRCPTR InstrGC,709 uint8_t *InstrHC, uint32_t *pOpsize, char *pszOutput,710 uint32_t fReadFlags = PATMREAD_ORGCODE)698 DECLINLINE(bool) PATMR3DISInstr(PVM pVM, PPATCHINFO pPatch, PDISCPUSTATE pCpu, RTRCPTR InstrGC, 699 uint8_t *InstrHC, uint32_t *pOpsize, char *pszOutput, 700 uint32_t fReadFlags = PATMREAD_ORGCODE) 711 701 { 712 702 PATMDISASM disinfo; … … 718 708 (pCpu)->pfnReadBytes = patmReadBytes; 719 709 (pCpu)->apvUserData[0] = &disinfo; 720 return RT_SUCCESS(DISInstr (pCpu, InstrGC, 0, pOpsize, pszOutput));710 return RT_SUCCESS(DISInstrWithReader(InstrGC, pCpu->mode, patmReadBytes, &disinfo, pCpu, pOpsize, pszOutput)); 721 711 } 722 712 #endif /* !IN_RC */ -
trunk/src/VBox/VMM/testcase/tstCompiler.cpp
r38636 r41658 204 204 205 205 memset(&Cpu, 0, sizeof(Cpu)); 206 Cpu.mode = CPUMODE_32BIT;207 206 do 208 207 { 209 208 char sz[256]; 210 209 uint32_t cbInstr = 0; 211 if (RT_SUCCESS(DISInstr( &Cpu, uCur, 0, &cbInstr, sz)))210 if (RT_SUCCESS(DISInstr(uCur, CPUMODE_32BIT, &Cpu, &cbInstr, sz))) 212 211 { 213 212 RTPrintf("tstBitFields: %s", sz); -
trunk/src/recompiler/VBoxREMWrapper.cpp
r40907 r41658 654 654 static const REMPARMDESC g_aArgsDISInstr[] = 655 655 { 656 { REMPARMDESC_FLAGS_INT, sizeof(PVM), NULL },657 656 { REMPARMDESC_FLAGS_INT, sizeof(RTUINTPTR), NULL }, 658 { REMPARMDESC_FLAGS_INT, sizeof(uint32_t), NULL }, 657 { REMPARMDESC_FLAGS_INT, sizeof(DISCPUMODE), NULL }, 658 { REMPARMDESC_FLAGS_INT, sizeof(PDISCPUSTATE), NULL }, 659 659 { REMPARMDESC_FLAGS_INT, sizeof(uint32_t *), NULL }, 660 660 { REMPARMDESC_FLAGS_INT, sizeof(char *), NULL } -
trunk/src/recompiler/VBoxRecompiler.c
r41436 r41658 4071 4071 char szOutput[256]; 4072 4072 DISCPUSTATE Cpu; 4073 4074 memset(&Cpu, 0, sizeof(Cpu));4075 4073 #ifdef RT_ARCH_X86 4076 Cpu.mode = CPUMODE_32BIT;4074 DISCPUMODE enmCpuMode = CPUMODE_32BIT; 4077 4075 #else 4078 Cpu.mode = CPUMODE_64BIT;4076 DISCPUMODE enmCpuMode = CPUMODE_64BIT; 4079 4077 #endif 4080 4078 … … 4083 4081 { 4084 4082 uint32_t cbInstr; 4085 if (RT_SUCCESS(DISInstr(&Cpu, (uintptr_t)pvCode + off, 0, &cbInstr, szOutput))) 4083 int rc = DISInstr((uintptr_t)pvCode + off, enmCpuMode, &Cpu, &cbInstr, szOutput); 4084 if (RT_SUCCESS(rc)) 4086 4085 RTLogPrintf("%s", szOutput); 4087 4086 else 4088 4087 { 4089 RTLogPrintf("disas error \n");4088 RTLogPrintf("disas error %Rrc\n", rc); 4090 4089 cbInstr = 1; 4091 #ifdef RT_ARCH_AMD64 /** @todo remove when DISInstr starts supporting 64-bit code. */4092 break;4093 #endif4094 4090 } 4095 4091 off += cbInstr;
Note:
See TracChangeset
for help on using the changeset viewer.