Changeset 97211 in vbox for trunk/src/VBox/Disassembler/DisasmMisc.cpp
- Timestamp:
- Oct 18, 2022 2:43:03 PM (2 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Disassembler/DisasmMisc.cpp
r97205 r97211 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox disassembler- Register InfoHelpers.3 * VBox disassembler- Misc Helpers. 4 4 */ 5 5 … … 42 42 43 43 44 /*********************************************************************************************************************************45 * Global Variables *46 *********************************************************************************************************************************/47 /**48 * Array for accessing 64-bit general registers in VMMREGFRAME structure49 * by register's index from disasm.50 */51 static const unsigned g_aReg64Index[] =52 {53 RT_OFFSETOF(CPUMCTXCORE, rax), /* DISGREG_RAX */54 RT_OFFSETOF(CPUMCTXCORE, rcx), /* DISGREG_RCX */55 RT_OFFSETOF(CPUMCTXCORE, rdx), /* DISGREG_RDX */56 RT_OFFSETOF(CPUMCTXCORE, rbx), /* DISGREG_RBX */57 RT_OFFSETOF(CPUMCTXCORE, rsp), /* DISGREG_RSP */58 RT_OFFSETOF(CPUMCTXCORE, rbp), /* DISGREG_RBP */59 RT_OFFSETOF(CPUMCTXCORE, rsi), /* DISGREG_RSI */60 RT_OFFSETOF(CPUMCTXCORE, rdi), /* DISGREG_RDI */61 RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8 */62 RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9 */63 RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R10 */64 RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11 */65 RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12 */66 RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13 */67 RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14 */68 RT_OFFSETOF(CPUMCTXCORE, r15) /* DISGREG_R15 */69 };70 71 /**72 * Macro for accessing 64-bit general purpose registers in CPUMCTXCORE structure.73 */74 #define DIS_READ_REG64(p, idx) (*(uint64_t *)((char *)(p) + g_aReg64Index[idx]))75 #define DIS_WRITE_REG64(p, idx, val) (*(uint64_t *)((char *)(p) + g_aReg64Index[idx]) = val)76 #define DIS_PTR_REG64(p, idx) ( (uint64_t *)((char *)(p) + g_aReg64Index[idx]))77 78 /**79 * Array for accessing 32-bit general registers in VMMREGFRAME structure80 * by register's index from disasm.81 */82 static const unsigned g_aReg32Index[] =83 {84 RT_OFFSETOF(CPUMCTXCORE, eax), /* DISGREG_EAX */85 RT_OFFSETOF(CPUMCTXCORE, ecx), /* DISGREG_ECX */86 RT_OFFSETOF(CPUMCTXCORE, edx), /* DISGREG_EDX */87 RT_OFFSETOF(CPUMCTXCORE, ebx), /* DISGREG_EBX */88 RT_OFFSETOF(CPUMCTXCORE, esp), /* DISGREG_ESP */89 RT_OFFSETOF(CPUMCTXCORE, ebp), /* DISGREG_EBP */90 RT_OFFSETOF(CPUMCTXCORE, esi), /* DISGREG_ESI */91 RT_OFFSETOF(CPUMCTXCORE, edi), /* DISGREG_EDI */92 RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8D */93 RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9D */94 RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R1D */95 RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11D */96 RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12D */97 RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13D */98 RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14D */99 RT_OFFSETOF(CPUMCTXCORE, r15) /* DISGREG_R15D */100 };101 102 /**103 * Macro for accessing 32-bit general purpose registers in CPUMCTXCORE structure.104 */105 #define DIS_READ_REG32(p, idx) (*(uint32_t *)((char *)(p) + g_aReg32Index[idx]))106 /* From http://www.cs.cmu.edu/~fp/courses/15213-s06/misc/asm64-handout.pdf:107 * ``Perhaps unexpectedly, instructions that move or generate 32-bit register108 * values also set the upper 32 bits of the register to zero. Consequently109 * there is no need for an instruction movzlq.''110 */111 #define DIS_WRITE_REG32(p, idx, val) (*(uint64_t *)((char *)(p) + g_aReg32Index[idx]) = (uint32_t)val)112 #define DIS_PTR_REG32(p, idx) ( (uint32_t *)((char *)(p) + g_aReg32Index[idx]))113 114 /**115 * Array for accessing 16-bit general registers in CPUMCTXCORE structure116 * by register's index from disasm.117 */118 static const unsigned g_aReg16Index[] =119 {120 RT_OFFSETOF(CPUMCTXCORE, eax), /* DISGREG_AX */121 RT_OFFSETOF(CPUMCTXCORE, ecx), /* DISGREG_CX */122 RT_OFFSETOF(CPUMCTXCORE, edx), /* DISGREG_DX */123 RT_OFFSETOF(CPUMCTXCORE, ebx), /* DISGREG_BX */124 RT_OFFSETOF(CPUMCTXCORE, esp), /* DISGREG_SP */125 RT_OFFSETOF(CPUMCTXCORE, ebp), /* DISGREG_BP */126 RT_OFFSETOF(CPUMCTXCORE, esi), /* DISGREG_SI */127 RT_OFFSETOF(CPUMCTXCORE, edi), /* DISGREG_DI */128 RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8W */129 RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9W */130 RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R10W */131 RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11W */132 RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12W */133 RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13W */134 RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14W */135 RT_OFFSETOF(CPUMCTXCORE, r15) /* DISGREG_R15W */136 };137 138 /**139 * Macro for accessing 16-bit general purpose registers in CPUMCTXCORE structure.140 */141 #define DIS_READ_REG16(p, idx) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]))142 #define DIS_WRITE_REG16(p, idx, val) (*(uint16_t *)((char *)(p) + g_aReg16Index[idx]) = val)143 #define DIS_PTR_REG16(p, idx) ( (uint16_t *)((char *)(p) + g_aReg16Index[idx]))144 145 /**146 * Array for accessing 8-bit general registers in CPUMCTXCORE structure147 * by register's index from disasm.148 */149 static const unsigned g_aReg8Index[] =150 {151 RT_OFFSETOF(CPUMCTXCORE, eax), /* DISGREG_AL */152 RT_OFFSETOF(CPUMCTXCORE, ecx), /* DISGREG_CL */153 RT_OFFSETOF(CPUMCTXCORE, edx), /* DISGREG_DL */154 RT_OFFSETOF(CPUMCTXCORE, ebx), /* DISGREG_BL */155 RT_OFFSETOF_ADD(CPUMCTXCORE, eax, 1), /* DISGREG_AH */156 RT_OFFSETOF_ADD(CPUMCTXCORE, ecx, 1), /* DISGREG_CH */157 RT_OFFSETOF_ADD(CPUMCTXCORE, edx, 1), /* DISGREG_DH */158 RT_OFFSETOF_ADD(CPUMCTXCORE, ebx, 1), /* DISGREG_BH */159 RT_OFFSETOF(CPUMCTXCORE, r8), /* DISGREG_R8B */160 RT_OFFSETOF(CPUMCTXCORE, r9), /* DISGREG_R9B */161 RT_OFFSETOF(CPUMCTXCORE, r10), /* DISGREG_R10B*/162 RT_OFFSETOF(CPUMCTXCORE, r11), /* DISGREG_R11B */163 RT_OFFSETOF(CPUMCTXCORE, r12), /* DISGREG_R12B */164 RT_OFFSETOF(CPUMCTXCORE, r13), /* DISGREG_R13B */165 RT_OFFSETOF(CPUMCTXCORE, r14), /* DISGREG_R14B */166 RT_OFFSETOF(CPUMCTXCORE, r15), /* DISGREG_R15B */167 RT_OFFSETOF(CPUMCTXCORE, esp), /* DISGREG_SPL; with REX prefix only */168 RT_OFFSETOF(CPUMCTXCORE, ebp), /* DISGREG_BPL; with REX prefix only */169 RT_OFFSETOF(CPUMCTXCORE, esi), /* DISGREG_SIL; with REX prefix only */170 RT_OFFSETOF(CPUMCTXCORE, edi) /* DISGREG_DIL; with REX prefix only */171 };172 173 /**174 * Macro for accessing 8-bit general purpose registers in CPUMCTXCORE structure.175 */176 #define DIS_READ_REG8(p, idx) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]))177 #define DIS_WRITE_REG8(p, idx, val) (*(uint8_t *)((char *)(p) + g_aReg8Index[idx]) = val)178 #define DIS_PTR_REG8(p, idx) ( (uint8_t *)((char *)(p) + g_aReg8Index[idx]))179 180 /**181 * Array for accessing segment registers in CPUMCTXCORE structure182 * by register's index from disasm.183 */184 static const unsigned g_aRegSegIndex[] =185 {186 RT_OFFSETOF(CPUMCTXCORE, es), /* DISSELREG_ES */187 RT_OFFSETOF(CPUMCTXCORE, cs), /* DISSELREG_CS */188 RT_OFFSETOF(CPUMCTXCORE, ss), /* DISSELREG_SS */189 RT_OFFSETOF(CPUMCTXCORE, ds), /* DISSELREG_DS */190 RT_OFFSETOF(CPUMCTXCORE, fs), /* DISSELREG_FS */191 RT_OFFSETOF(CPUMCTXCORE, gs) /* DISSELREG_GS */192 };193 194 /**195 * Macro for accessing segment registers in CPUMCTXCORE structure.196 */197 #define DIS_READ_REGSEG(p, idx) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])))198 #define DIS_WRITE_REGSEG(p, idx, val) (*((uint16_t *)((char *)(p) + g_aRegSegIndex[idx])) = val)199 200 201 //*****************************************************************************202 //*****************************************************************************203 44 DISDECL(uint8_t) DISGetParamSize(PCDISSTATE pDis, PCDISOPPARAM pParam) 204 45 { … … 287 128 } 288 129 } 289 //***************************************************************************** 290 //***************************************************************************** 130 131 #if 0 /* currently unused */ 291 132 DISDECL(DISSELREG) DISDetectSegReg(PCDISSTATE pDis, PCDISOPPARAM pParam) 292 133 { … … 308 149 return DISSELREG_DS; 309 150 } 310 //***************************************************************************** 311 //***************************************************************************** 151 152 312 153 DISDECL(uint8_t) DISQuerySegPrefixByte(PCDISSTATE pDis) 313 154 { … … 332 173 } 333 174 } 334 335 336 337 /** 338 * Returns the value of the specified 8 bits general purpose register 339 * 340 */ 341 DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal) 342 { 343 AssertReturnStmt(reg8 < RT_ELEMENTS(g_aReg8Index), *pVal = 0, VERR_INVALID_PARAMETER); 344 345 *pVal = DIS_READ_REG8(pCtx, reg8); 346 return VINF_SUCCESS; 347 } 348 349 /** 350 * Returns the value of the specified 16 bits general purpose register 351 * 352 */ 353 DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal) 354 { 355 AssertReturnStmt(reg16 < RT_ELEMENTS(g_aReg16Index), *pVal = 0, VERR_INVALID_PARAMETER); 356 357 *pVal = DIS_READ_REG16(pCtx, reg16); 358 return VINF_SUCCESS; 359 } 360 361 /** 362 * Returns the value of the specified 32 bits general purpose register 363 * 364 */ 365 DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal) 366 { 367 AssertReturnStmt(reg32 < RT_ELEMENTS(g_aReg32Index), *pVal = 0, VERR_INVALID_PARAMETER); 368 369 *pVal = DIS_READ_REG32(pCtx, reg32); 370 return VINF_SUCCESS; 371 } 372 373 /** 374 * Returns the value of the specified 64 bits general purpose register 375 * 376 */ 377 DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal) 378 { 379 AssertReturnStmt(reg64 < RT_ELEMENTS(g_aReg64Index), *pVal = 0, VERR_INVALID_PARAMETER); 380 381 *pVal = DIS_READ_REG64(pCtx, reg64); 382 return VINF_SUCCESS; 383 } 384 385 /** 386 * Returns the pointer to the specified 8 bits general purpose register 387 * 388 */ 389 DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg) 390 { 391 AssertReturnStmt(reg8 < RT_ELEMENTS(g_aReg8Index), *ppReg = NULL, VERR_INVALID_PARAMETER); 392 393 *ppReg = DIS_PTR_REG8(pCtx, reg8); 394 return VINF_SUCCESS; 395 } 396 397 /** 398 * Returns the pointer to the specified 16 bits general purpose register 399 * 400 */ 401 DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg) 402 { 403 AssertReturnStmt(reg16 < RT_ELEMENTS(g_aReg16Index), *ppReg = NULL, VERR_INVALID_PARAMETER); 404 405 *ppReg = DIS_PTR_REG16(pCtx, reg16); 406 return VINF_SUCCESS; 407 } 408 409 /** 410 * Returns the pointer to the specified 32 bits general purpose register 411 */ 412 DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg) 413 { 414 AssertReturnStmt(reg32 < RT_ELEMENTS(g_aReg32Index), *ppReg = NULL, VERR_INVALID_PARAMETER); 415 416 *ppReg = DIS_PTR_REG32(pCtx, reg32); 417 return VINF_SUCCESS; 418 } 419 420 /** 421 * Returns the pointer to the specified 64 bits general purpose register 422 */ 423 DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg) 424 { 425 AssertReturnStmt(reg64 < RT_ELEMENTS(g_aReg64Index), *ppReg = NULL, VERR_INVALID_PARAMETER); 426 427 *ppReg = DIS_PTR_REG64(pCtx, reg64); 428 return VINF_SUCCESS; 429 } 430 431 /** 432 * Returns the value of the specified segment register 433 */ 434 DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DISSELREG sel, RTSEL *pVal) 435 { 436 AssertReturn((unsigned)sel < RT_ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER); 437 438 AssertCompile(sizeof(uint16_t) == sizeof(RTSEL)); 439 *pVal = DIS_READ_REGSEG(pCtx, sel); 440 return VINF_SUCCESS; 441 } 442 443 /** 444 * Updates the value of the specified 64 bits general purpose register 445 * 446 */ 447 DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64) 448 { 449 AssertReturn(reg64 < RT_ELEMENTS(g_aReg64Index), VERR_INVALID_PARAMETER); 450 451 DIS_WRITE_REG64(pRegFrame, reg64, val64); 452 return VINF_SUCCESS; 453 } 454 455 /** 456 * Updates the value of the specified 32 bits general purpose register 457 * 458 */ 459 DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32) 460 { 461 AssertReturn(reg32 < RT_ELEMENTS(g_aReg32Index), VERR_INVALID_PARAMETER); 462 463 DIS_WRITE_REG32(pRegFrame, reg32, val32); 464 return VINF_SUCCESS; 465 } 466 467 /** 468 * Updates the value of the specified 16 bits general purpose register 469 * 470 */ 471 DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg16, uint16_t val16) 472 { 473 AssertReturn(reg16 < RT_ELEMENTS(g_aReg16Index), VERR_INVALID_PARAMETER); 474 475 DIS_WRITE_REG16(pRegFrame, reg16, val16); 476 return VINF_SUCCESS; 477 } 478 479 /** 480 * Updates the specified 8 bits general purpose register 481 * 482 */ 483 DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8) 484 { 485 AssertReturn(reg8 < RT_ELEMENTS(g_aReg8Index), VERR_INVALID_PARAMETER); 486 487 DIS_WRITE_REG8(pRegFrame, reg8, val8); 488 return VINF_SUCCESS; 489 } 490 491 /** 492 * Updates the specified segment register 493 * 494 */ 495 DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DISSELREG sel, RTSEL val) 496 { 497 AssertReturn((unsigned)sel < RT_ELEMENTS(g_aRegSegIndex), VERR_INVALID_PARAMETER); 498 499 AssertCompile(sizeof(uint16_t) == sizeof(RTSEL)); 500 DIS_WRITE_REGSEG(pCtx, sel, val); 501 return VINF_SUCCESS; 502 } 503 504 /** 505 * Returns the value of the parameter in pParam 506 * 507 * @returns VBox error code 508 * @param pCtx CPU context structure pointer 509 * @param pDis Pointer to the disassembler state. 510 * @param pParam Pointer to the parameter to parse 511 * @param pParamVal Pointer to parameter value (OUT) 512 * @param parmtype Parameter type 513 * 514 * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!! 515 * 516 */ 517 DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, PDISQPVPARAMVAL pParamVal, DISQPVWHICH parmtype) 518 { 519 memset(pParamVal, 0, sizeof(*pParamVal)); 520 521 if (DISUSE_IS_EFFECTIVE_ADDR(pParam->fUse)) 522 { 523 // Effective address 524 pParamVal->type = DISQPV_TYPE_ADDRESS; 525 pParamVal->size = pParam->cb; 526 527 if (pParam->fUse & DISUSE_BASE) 528 { 529 if (pParam->fUse & DISUSE_REG_GEN8) 530 { 531 pParamVal->flags |= DISQPV_FLAG_8; 532 if (RT_FAILURE(DISFetchReg8(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER; 533 } 534 else 535 if (pParam->fUse & DISUSE_REG_GEN16) 536 { 537 pParamVal->flags |= DISQPV_FLAG_16; 538 if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER; 539 } 540 else 541 if (pParam->fUse & DISUSE_REG_GEN32) 542 { 543 pParamVal->flags |= DISQPV_FLAG_32; 544 if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER; 545 } 546 else 547 if (pParam->fUse & DISUSE_REG_GEN64) 548 { 549 pParamVal->flags |= DISQPV_FLAG_64; 550 if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER; 551 } 552 else 553 { 554 AssertFailed(); 555 return VERR_INVALID_PARAMETER; 556 } 557 } 558 // Note that scale implies index (SIB byte) 559 if (pParam->fUse & DISUSE_INDEX) 560 { 561 if (pParam->fUse & DISUSE_REG_GEN16) 562 { 563 uint16_t val16; 564 565 pParamVal->flags |= DISQPV_FLAG_16; 566 if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Index.idxGenReg, &val16))) return VERR_INVALID_PARAMETER; 567 568 Assert(!(pParam->fUse & DISUSE_SCALE)); /* shouldn't be possible in 16 bits mode */ 569 570 pParamVal->val.val16 += val16; 571 } 572 else 573 if (pParam->fUse & DISUSE_REG_GEN32) 574 { 575 uint32_t val32; 576 577 pParamVal->flags |= DISQPV_FLAG_32; 578 if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Index.idxGenReg, &val32))) return VERR_INVALID_PARAMETER; 579 580 if (pParam->fUse & DISUSE_SCALE) 581 val32 *= pParam->uScale; 582 583 pParamVal->val.val32 += val32; 584 } 585 else 586 if (pParam->fUse & DISUSE_REG_GEN64) 587 { 588 uint64_t val64; 589 590 pParamVal->flags |= DISQPV_FLAG_64; 591 if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Index.idxGenReg, &val64))) return VERR_INVALID_PARAMETER; 592 593 if (pParam->fUse & DISUSE_SCALE) 594 val64 *= pParam->uScale; 595 596 pParamVal->val.val64 += val64; 597 } 598 else 599 AssertFailed(); 600 } 601 602 if (pParam->fUse & DISUSE_DISPLACEMENT8) 603 { 604 if (pDis->uCpuMode == DISCPUMODE_32BIT) 605 pParamVal->val.i32 += (int32_t)pParam->uDisp.i8; 606 else if (pDis->uCpuMode == DISCPUMODE_64BIT) 607 pParamVal->val.i64 += (int64_t)pParam->uDisp.i8; 608 else 609 pParamVal->val.i16 += (int16_t)pParam->uDisp.i8; 610 } 611 else if (pParam->fUse & DISUSE_DISPLACEMENT16) 612 { 613 if (pDis->uCpuMode == DISCPUMODE_32BIT) 614 pParamVal->val.i32 += (int32_t)pParam->uDisp.i16; 615 else if (pDis->uCpuMode == DISCPUMODE_64BIT) 616 pParamVal->val.i64 += (int64_t)pParam->uDisp.i16; 617 else 618 pParamVal->val.i16 += pParam->uDisp.i16; 619 } 620 else if (pParam->fUse & DISUSE_DISPLACEMENT32) 621 { 622 if (pDis->uCpuMode == DISCPUMODE_32BIT) 623 pParamVal->val.i32 += pParam->uDisp.i32; 624 else 625 pParamVal->val.i64 += pParam->uDisp.i32; 626 } 627 else if (pParam->fUse & DISUSE_DISPLACEMENT64) 628 { 629 Assert(pDis->uCpuMode == DISCPUMODE_64BIT); 630 pParamVal->val.i64 += pParam->uDisp.i64; 631 } 632 else if (pParam->fUse & DISUSE_RIPDISPLACEMENT32) 633 { 634 Assert(pDis->uCpuMode == DISCPUMODE_64BIT); 635 /* Relative to the RIP of the next instruction. */ 636 pParamVal->val.i64 += pParam->uDisp.i32 + pCtx->rip + pDis->cbInstr; 637 } 638 return VINF_SUCCESS; 639 } 640 641 if (pParam->fUse & (DISUSE_REG_GEN8|DISUSE_REG_GEN16|DISUSE_REG_GEN32|DISUSE_REG_GEN64|DISUSE_REG_FP|DISUSE_REG_MMX|DISUSE_REG_XMM|DISUSE_REG_CR|DISUSE_REG_DBG|DISUSE_REG_SEG|DISUSE_REG_TEST)) 642 { 643 if (parmtype == DISQPVWHICH_DST) 644 { 645 // Caller needs to interpret the register according to the instruction (source/target, special value etc) 646 pParamVal->type = DISQPV_TYPE_REGISTER; 647 pParamVal->size = pParam->cb; 648 return VINF_SUCCESS; 649 } 650 //else DISQPVWHICH_SRC 651 652 pParamVal->type = DISQPV_TYPE_IMMEDIATE; 653 654 if (pParam->fUse & DISUSE_REG_GEN8) 655 { 656 pParamVal->flags |= DISQPV_FLAG_8; 657 pParamVal->size = sizeof(uint8_t); 658 if (RT_FAILURE(DISFetchReg8(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val8))) return VERR_INVALID_PARAMETER; 659 } 660 else 661 if (pParam->fUse & DISUSE_REG_GEN16) 662 { 663 pParamVal->flags |= DISQPV_FLAG_16; 664 pParamVal->size = sizeof(uint16_t); 665 if (RT_FAILURE(DISFetchReg16(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val16))) return VERR_INVALID_PARAMETER; 666 } 667 else 668 if (pParam->fUse & DISUSE_REG_GEN32) 669 { 670 pParamVal->flags |= DISQPV_FLAG_32; 671 pParamVal->size = sizeof(uint32_t); 672 if (RT_FAILURE(DISFetchReg32(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val32))) return VERR_INVALID_PARAMETER; 673 } 674 else 675 if (pParam->fUse & DISUSE_REG_GEN64) 676 { 677 pParamVal->flags |= DISQPV_FLAG_64; 678 pParamVal->size = sizeof(uint64_t); 679 if (RT_FAILURE(DISFetchReg64(pCtx, pParam->Base.idxGenReg, &pParamVal->val.val64))) return VERR_INVALID_PARAMETER; 680 } 681 else 682 { 683 // Caller needs to interpret the register according to the instruction (source/target, special value etc) 684 pParamVal->type = DISQPV_TYPE_REGISTER; 685 } 686 Assert(!(pParam->fUse & DISUSE_IMMEDIATE)); 687 return VINF_SUCCESS; 688 } 689 690 if (pParam->fUse & DISUSE_IMMEDIATE) 691 { 692 pParamVal->type = DISQPV_TYPE_IMMEDIATE; 693 if (pParam->fUse & (DISUSE_IMMEDIATE8|DISUSE_IMMEDIATE8_REL)) 694 { 695 pParamVal->flags |= DISQPV_FLAG_8; 696 if (pParam->cb == 2) 697 { 698 pParamVal->size = sizeof(uint16_t); 699 pParamVal->val.val16 = (uint8_t)pParam->uValue; 700 } 701 else 702 { 703 pParamVal->size = sizeof(uint8_t); 704 pParamVal->val.val8 = (uint8_t)pParam->uValue; 705 } 706 } 707 else 708 if (pParam->fUse & (DISUSE_IMMEDIATE16|DISUSE_IMMEDIATE16_REL|DISUSE_IMMEDIATE_ADDR_0_16|DISUSE_IMMEDIATE16_SX8)) 709 { 710 pParamVal->flags |= DISQPV_FLAG_16; 711 pParamVal->size = sizeof(uint16_t); 712 pParamVal->val.val16 = (uint16_t)pParam->uValue; 713 AssertMsg(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE16_SX8)), ("pParamVal->size %d vs %d EIP=%RX32\n", pParamVal->size, pParam->cb, pCtx->eip) ); 714 } 715 else 716 if (pParam->fUse & (DISUSE_IMMEDIATE32|DISUSE_IMMEDIATE32_REL|DISUSE_IMMEDIATE_ADDR_0_32|DISUSE_IMMEDIATE32_SX8)) 717 { 718 pParamVal->flags |= DISQPV_FLAG_32; 719 pParamVal->size = sizeof(uint32_t); 720 pParamVal->val.val32 = (uint32_t)pParam->uValue; 721 Assert(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE32_SX8)) ); 722 } 723 else 724 if (pParam->fUse & (DISUSE_IMMEDIATE64 | DISUSE_IMMEDIATE64_REL | DISUSE_IMMEDIATE64_SX8)) 725 { 726 pParamVal->flags |= DISQPV_FLAG_64; 727 pParamVal->size = sizeof(uint64_t); 728 pParamVal->val.val64 = pParam->uValue; 729 Assert(pParamVal->size == pParam->cb || ((pParam->cb == 1) && (pParam->fUse & DISUSE_IMMEDIATE64_SX8)) ); 730 } 731 else 732 if (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_16)) 733 { 734 pParamVal->flags |= DISQPV_FLAG_FARPTR16; 735 pParamVal->size = sizeof(uint16_t)*2; 736 pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->uValue >> 16); 737 pParamVal->val.farptr.offset = (uint32_t)RT_LOWORD(pParam->uValue); 738 Assert(pParamVal->size == pParam->cb); 739 } 740 else 741 if (pParam->fUse & (DISUSE_IMMEDIATE_ADDR_16_32)) 742 { 743 pParamVal->flags |= DISQPV_FLAG_FARPTR32; 744 pParamVal->size = sizeof(uint16_t) + sizeof(uint32_t); 745 pParamVal->val.farptr.sel = (uint16_t)RT_LOWORD(pParam->uValue >> 32); 746 pParamVal->val.farptr.offset = (uint32_t)(pParam->uValue & 0xFFFFFFFF); 747 Assert(pParam->cb == 8); 748 } 749 } 750 return VINF_SUCCESS; 751 } 752 753 /** 754 * Returns the pointer to a register of the parameter in pParam. We need this 755 * pointer when an interpreted instruction updates a register as a side effect. 756 * In CMPXCHG we know that only [r/e]ax is updated, but with XADD this could 757 * be every register. 758 * 759 * @returns VBox error code 760 * @param pCtx CPU context structure pointer 761 * @param pDis Pointer to the disassembler state. 762 * @param pParam Pointer to the parameter to parse 763 * @param pReg Pointer to parameter value (OUT) 764 * @param cbsize Parameter size (OUT) 765 * 766 * @note Currently doesn't handle FPU/XMM/MMX/3DNow! parameters correctly!! 767 * 768 */ 769 DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, void **ppReg, size_t *pcbSize) 770 { 771 NOREF(pDis); 772 if (pParam->fUse & (DISUSE_REG_GEN8|DISUSE_REG_GEN16|DISUSE_REG_GEN32|DISUSE_REG_FP|DISUSE_REG_MMX|DISUSE_REG_XMM|DISUSE_REG_CR|DISUSE_REG_DBG|DISUSE_REG_SEG|DISUSE_REG_TEST)) 773 { 774 if (pParam->fUse & DISUSE_REG_GEN8) 775 { 776 uint8_t *pu8Reg; 777 if (RT_SUCCESS(DISPtrReg8(pCtx, pParam->Base.idxGenReg, &pu8Reg))) 778 { 779 *pcbSize = sizeof(uint8_t); 780 *ppReg = (void *)pu8Reg; 781 return VINF_SUCCESS; 782 } 783 } 784 else 785 if (pParam->fUse & DISUSE_REG_GEN16) 786 { 787 uint16_t *pu16Reg; 788 if (RT_SUCCESS(DISPtrReg16(pCtx, pParam->Base.idxGenReg, &pu16Reg))) 789 { 790 *pcbSize = sizeof(uint16_t); 791 *ppReg = (void *)pu16Reg; 792 return VINF_SUCCESS; 793 } 794 } 795 else 796 if (pParam->fUse & DISUSE_REG_GEN32) 797 { 798 uint32_t *pu32Reg; 799 if (RT_SUCCESS(DISPtrReg32(pCtx, pParam->Base.idxGenReg, &pu32Reg))) 800 { 801 *pcbSize = sizeof(uint32_t); 802 *ppReg = (void *)pu32Reg; 803 return VINF_SUCCESS; 804 } 805 } 806 else 807 if (pParam->fUse & DISUSE_REG_GEN64) 808 { 809 uint64_t *pu64Reg; 810 if (RT_SUCCESS(DISPtrReg64(pCtx, pParam->Base.idxGenReg, &pu64Reg))) 811 { 812 *pcbSize = sizeof(uint64_t); 813 *ppReg = (void *)pu64Reg; 814 return VINF_SUCCESS; 815 } 816 } 817 } 818 return VERR_INVALID_PARAMETER; 819 } 820 175 #endif
Note:
See TracChangeset
for help on using the changeset viewer.