diff --git a/bddisasm/bddisasm.c b/bddisasm/bddisasm.c index 22bc236..1b232c3 100644 --- a/bddisasm/bddisasm.c +++ b/bddisasm/bddisasm.c @@ -1719,6 +1719,7 @@ NdParseOperand( operand->Info.Register.Type = ND_REG_SEG; operand->Info.Register.Size = (ND_REG_SIZE)size; operand->Info.Register.Reg = NDR_CS; + Instrux->CsAccess |= operand->Access.Access; break; case ND_OPT_SEG_SS: @@ -4101,6 +4102,18 @@ NdDecodeWithContext( Instrux->IsCetTracked = ND_HAS_CETT(Instrux) && ((!ND_DNT_SUPPORT(Instrux)) || (Instrux->Seg != ND_PREFIX_G2_NO_TRACK)); + // Fill in branch information. + if (!!(Instrux->RipAccess & ND_ACCESS_ANY_WRITE)) + { + Instrux->BranchInfo.IsBranch = 1; + Instrux->BranchInfo.IsConditional = Instrux->Category == ND_CAT_COND_BR; + // Indirect branches are those which get their target address from a register or memory, including RET familly. + Instrux->BranchInfo.IsIndirect = ((!Instrux->Operands[0].Flags.IsDefault) && + (Instrux->Operands[0].Type == ND_OP_REG) || (Instrux->Operands[0].Type == ND_OP_MEM)) || + (Instrux->Category == ND_CAT_RET); + Instrux->BranchInfo.IsFar = !!(Instrux->CsAccess & ND_ACCESS_ANY_WRITE); + } + // Do instruction validations. These checks are made in order to filter out encodings that would normally // be invalid and would generate #UD. status = NdValidateInstruction(Instrux); @@ -4145,212 +4158,9 @@ NdDecode( } - - -// -// NdIsInstruxRipRelative -// -bool -NdIsInstruxRipRelative( - const INSTRUX *Instrux - ) -// -// Provided for backwards compatibility with existing code that uses disasm 1.0 -// -{ - if (NULL == Instrux) - { - return false; - } - else - { - return Instrux->IsRipRelative; - } -} - - // -// NdGetFullAccessMap +// NdInitContext // -NDSTATUS -NdGetFullAccessMap( - const INSTRUX *Instrux, - ND_ACCESS_MAP *AccessMap - ) -{ - uint32_t i; - const ND_OPERAND *pOp; - - // pre-init - i = 0; - pOp = NULL; - - // validate - if (NULL == Instrux) - { - return ND_STATUS_INVALID_PARAMETER; - } - - if (NULL == AccessMap) - { - return ND_STATUS_INVALID_PARAMETER; - } - - for (i = 0; i < Instrux->OperandsCount; i++) - { - pOp = &Instrux->Operands[i]; - - if (ND_OP_MEM == pOp->Type) - { - if (pOp->Info.Memory.IsStack) - { - AccessMap->StackAccess |= pOp->Access.Access; - AccessMap->GprAccess[NDR_RSP] |= ND_ACCESS_READ|ND_ACCESS_WRITE; - AccessMap->SegAccess[NDR_SS] |= ND_ACCESS_READ; - } - else - { - AccessMap->MemAccess |= pOp->Access.Access; - - if (pOp->Info.Memory.HasSeg) - { - AccessMap->SegAccess[pOp->Info.Memory.Seg] |= ND_ACCESS_READ; - } - - if (pOp->Info.Memory.HasBase) - { - AccessMap->GprAccess[pOp->Info.Memory.Base] |= ND_ACCESS_READ; - } - - if (pOp->Info.Memory.HasIndex) - { - if (pOp->Info.Memory.IsVsib) - { - AccessMap->SseAccess[pOp->Info.Memory.Index] |= ND_ACCESS_READ; - } - else - { - AccessMap->GprAccess[pOp->Info.Memory.Index] |= ND_ACCESS_READ; - } - } - } - } - else if (ND_OP_REG == pOp->Type) - { - switch (pOp->Info.Register.Type) - { - case ND_REG_GPR: - { - uint32_t k; - - for (k = 0; k < pOp->Info.Register.Count; k++) - { - AccessMap->GprAccess[pOp->Info.Register.Reg + k] |= pOp->Access.Access; - } - } - break; - case ND_REG_SEG: - AccessMap->SegAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; - break; - case ND_REG_FPU: - AccessMap->FpuAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; - break; - case ND_REG_MMX: - AccessMap->MmxAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; - break; - case ND_REG_SSE: - { - uint32_t k; - - for (k = 0; k < pOp->Info.Register.Count; k++) - { - AccessMap->SseAccess[pOp->Info.Register.Reg + k] |= pOp->Access.Access; - } - } - break; - case ND_REG_CR: - AccessMap->CrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; - break; - case ND_REG_DR: - AccessMap->DrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; - break; - case ND_REG_TR: - AccessMap->TrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; - break; - case ND_REG_BND: - AccessMap->BndAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; - break; - case ND_REG_MSK: - AccessMap->MskAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; - break; - case ND_REG_SYS: - AccessMap->SysAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; - break; - case ND_REG_X87: - AccessMap->X87Access[pOp->Info.Register.Reg] |= pOp->Access.Access; - break; - case ND_REG_FLG: - AccessMap->FlagsAccess |= pOp->Access.Access; - break; - case ND_REG_RIP: - AccessMap->RipAccess |= pOp->Access.Access; - break; - case ND_REG_MXCSR: - AccessMap->MxcsrAccess |= pOp->Access.Access; - break; - case ND_REG_PKRU: - AccessMap->PkruAccess |= pOp->Access.Access; - break; - case ND_REG_SSP: - AccessMap->SspAccess |= pOp->Access.Access; - break; - default: - break; - } - } - else if (ND_OP_BANK == Instrux->Operands[i].Type) - { - uint8_t j; - - // Bank registers access. This needs special handling. Note that LOADALL/LOADALLD is not supported, as - // it is too old and it's not valid since the good old 486. - if (ND_INS_FNSAVE == Instrux->Instruction) - { - for (j = 0; j < ND_MAX_FPU_REGS; j++) - { - AccessMap->FpuAccess[j] |= ND_ACCESS_READ; - } - } - else if (ND_INS_FRSTOR == Instrux->Instruction) - { - for (j = 0; j < ND_MAX_FPU_REGS; j++) - { - AccessMap->FpuAccess[j] |= ND_ACCESS_WRITE; - } - } - - if ((ND_INS_XSAVE == Instrux->Instruction) || (ND_INS_XSAVEOPT == Instrux->Instruction) || - (ND_INS_XSAVES == Instrux->Instruction) || (ND_INS_XSAVEC == Instrux->Instruction)) - { - for (j = 0; j < ND_MAX_SSE_REGS; j++) - { - AccessMap->SseAccess[j] |= ND_ACCESS_READ; - } - } - else if ((ND_INS_XRSTOR == Instrux->Instruction) || (ND_INS_XRSTORS == Instrux->Instruction)) - { - for (j = 0; j < ND_MAX_SSE_REGS; j++) - { - AccessMap->SseAccess[j] |= ND_ACCESS_WRITE; - } - } - } - } - - return ND_STATUS_SUCCESS; -} - - void NdInitContext( ND_CONTEXT *Context diff --git a/bddisasm/bddisasm.vcxproj b/bddisasm/bddisasm.vcxproj index ae1cbf3..abcd197 100644 --- a/bddisasm/bddisasm.vcxproj +++ b/bddisasm/bddisasm.vcxproj @@ -421,6 +421,7 @@ + NotUsing diff --git a/bddisasm/bddisasm.vcxproj.filters b/bddisasm/bddisasm.vcxproj.filters index b4de484..b8052d0 100644 --- a/bddisasm/bddisasm.vcxproj.filters +++ b/bddisasm/bddisasm.vcxproj.filters @@ -30,6 +30,9 @@ Source Files + + Source Files + diff --git a/bddisasm/bdhelpers.c b/bddisasm/bdhelpers.c new file mode 100644 index 0000000..72ba1b0 --- /dev/null +++ b/bddisasm/bdhelpers.c @@ -0,0 +1,321 @@ +#include "include/nd_crt.h" +#include "../inc/bddisasm.h" + + +// +// NdIsInstruxRipRelative +// +bool +NdIsInstruxRipRelative( + const INSTRUX *Instrux + ) +// +// Provided for backwards compatibility with existing code that uses disasm 1.0 +// +{ + if (NULL == Instrux) + { + return false; + } + else + { + return Instrux->IsRipRelative; + } +} + + +// +// NdGetFullAccessMap +// +NDSTATUS +NdGetFullAccessMap( + const INSTRUX *Instrux, + ND_ACCESS_MAP *AccessMap + ) +{ + uint32_t i; + const ND_OPERAND *pOp; + + // pre-init + i = 0; + pOp = NULL; + + // validate + if (NULL == Instrux) + { + return ND_STATUS_INVALID_PARAMETER; + } + + if (NULL == AccessMap) + { + return ND_STATUS_INVALID_PARAMETER; + } + + for (i = 0; i < Instrux->OperandsCount; i++) + { + pOp = &Instrux->Operands[i]; + + if (ND_OP_MEM == pOp->Type) + { + if (pOp->Info.Memory.IsStack) + { + AccessMap->StackAccess |= pOp->Access.Access; + AccessMap->GprAccess[NDR_RSP] |= ND_ACCESS_READ|ND_ACCESS_WRITE; + AccessMap->SegAccess[NDR_SS] |= ND_ACCESS_READ; + } + else + { + AccessMap->MemAccess |= pOp->Access.Access; + + if (pOp->Info.Memory.HasSeg) + { + AccessMap->SegAccess[pOp->Info.Memory.Seg] |= ND_ACCESS_READ; + } + + if (pOp->Info.Memory.HasBase) + { + AccessMap->GprAccess[pOp->Info.Memory.Base] |= ND_ACCESS_READ; + } + + if (pOp->Info.Memory.HasIndex) + { + if (pOp->Info.Memory.IsVsib) + { + AccessMap->SseAccess[pOp->Info.Memory.Index] |= ND_ACCESS_READ; + } + else + { + AccessMap->GprAccess[pOp->Info.Memory.Index] |= ND_ACCESS_READ; + } + } + } + } + else if (ND_OP_REG == pOp->Type) + { + switch (pOp->Info.Register.Type) + { + case ND_REG_GPR: + { + uint32_t k; + + for (k = 0; k < pOp->Info.Register.Count; k++) + { + AccessMap->GprAccess[pOp->Info.Register.Reg + k] |= pOp->Access.Access; + } + } + break; + case ND_REG_SEG: + AccessMap->SegAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + case ND_REG_FPU: + AccessMap->FpuAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + case ND_REG_MMX: + AccessMap->MmxAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + case ND_REG_SSE: + { + uint32_t k; + + for (k = 0; k < pOp->Info.Register.Count; k++) + { + AccessMap->SseAccess[pOp->Info.Register.Reg + k] |= pOp->Access.Access; + } + } + break; + case ND_REG_CR: + AccessMap->CrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + case ND_REG_DR: + AccessMap->DrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + case ND_REG_TR: + AccessMap->TrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + case ND_REG_BND: + AccessMap->BndAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + case ND_REG_MSK: + AccessMap->MskAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + case ND_REG_SYS: + AccessMap->SysAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + case ND_REG_X87: + AccessMap->X87Access[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + case ND_REG_FLG: + AccessMap->FlagsAccess |= pOp->Access.Access; + break; + case ND_REG_RIP: + AccessMap->RipAccess |= pOp->Access.Access; + break; + case ND_REG_MXCSR: + AccessMap->MxcsrAccess |= pOp->Access.Access; + break; + case ND_REG_PKRU: + AccessMap->PkruAccess |= pOp->Access.Access; + break; + case ND_REG_SSP: + AccessMap->SspAccess |= pOp->Access.Access; + break; + case ND_REG_TILE: + AccessMap->TmmAccess[pOp->Info.Register.Reg] |= pOp->Access.Access; + break; + default: + break; + } + } + else if (ND_OP_BANK == Instrux->Operands[i].Type) + { + uint8_t j; + + // Bank registers access. This needs special handling. Note that LOADALL/LOADALLD is not supported, as + // it is too old and it's not valid since the good old 486. + if (ND_INS_FNSAVE == Instrux->Instruction) + { + for (j = 0; j < ND_MAX_FPU_REGS; j++) + { + AccessMap->FpuAccess[j] |= ND_ACCESS_READ; + } + } + else if (ND_INS_FRSTOR == Instrux->Instruction) + { + for (j = 0; j < ND_MAX_FPU_REGS; j++) + { + AccessMap->FpuAccess[j] |= ND_ACCESS_WRITE; + } + } + + if ((ND_INS_XSAVE == Instrux->Instruction) || (ND_INS_XSAVEOPT == Instrux->Instruction) || + (ND_INS_XSAVES == Instrux->Instruction) || (ND_INS_XSAVEC == Instrux->Instruction)) + { + for (j = 0; j < ND_MAX_SSE_REGS; j++) + { + AccessMap->SseAccess[j] |= ND_ACCESS_READ; + } + } + else if ((ND_INS_XRSTOR == Instrux->Instruction) || (ND_INS_XRSTORS == Instrux->Instruction)) + { + for (j = 0; j < ND_MAX_SSE_REGS; j++) + { + AccessMap->SseAccess[j] |= ND_ACCESS_WRITE; + } + } + } + } + + return ND_STATUS_SUCCESS; +} + + +// +// NdGetOperandRlut +// +NDSTATUS +NdGetOperandRlut( + INSTRUX *Instrux, + ND_OPERAND_RLUT *Rlut + ) +{ + if (NULL == Instrux) + { + return ND_STATUS_INVALID_PARAMETER; + } + + if (NULL == Rlut) + { + return ND_STATUS_INVALID_PARAMETER; + } + + // Initialize the RLUT. + nd_memset(Rlut, 0, sizeof(*Rlut)); + + for (uint8_t i = 0; i < Instrux->OperandsCount; i++) + { + if (!!(Instrux->Operands[i].Access.Access & ND_ACCESS_ANY_WRITE)) + { + // We only care about the first 2 destination operands. + if (Rlut->Dst1 == NULL) + { + Rlut->Dst1 = &Instrux->Operands[i]; + } + else if (Rlut->Dst2 == NULL) + { + Rlut->Dst2 = &Instrux->Operands[i]; + } + } + + if (!!(Instrux->Operands[i].Access.Access & ND_ACCESS_ANY_READ)) + { + // We only care about the first 4 source operands. + if (Rlut->Src1 == NULL) + { + Rlut->Src1 = &Instrux->Operands[i]; + } + else if (Rlut->Src2 == NULL) + { + Rlut->Src2 = &Instrux->Operands[i]; + } + else if (Rlut->Src3 == NULL) + { + Rlut->Src3 = &Instrux->Operands[i]; + } + else if (Rlut->Src4 == NULL) + { + Rlut->Src4 = &Instrux->Operands[i]; + } + } + + if (Instrux->Operands[i].Type == ND_OP_MEM) + { + // We only care about the first 2 memory operands. + if (Rlut->Mem1 == NULL) + { + Rlut->Mem1 = &Instrux->Operands[i]; + } + else if (Rlut->Mem2 == NULL) + { + Rlut->Mem2 = &Instrux->Operands[i]; + } + + if (Instrux->Operands[i].Info.Memory.IsStack) + { + Rlut->Stack = &Instrux->Operands[i]; + } + } + + if (Instrux->Operands[i].Type == ND_OP_REG && Instrux->Operands->Flags.IsDefault) + { + switch (Instrux->Operands[i].Info.Register.Type) + { + case ND_REG_FLG: + Rlut->Flags = &Instrux->Operands[i]; + break; + case ND_REG_RIP: + Rlut->Rip = &Instrux->Operands[i];; + break; + case ND_REG_SEG: + if (Instrux->Operands[i].Info.Register.Reg == NDR_CS) + { + Rlut->Cs = &Instrux->Operands[i]; + } + else if (Instrux->Operands[i].Info.Register.Reg == NDR_SS) + { + Rlut->Ss = &Instrux->Operands[i]; + } + break; + case ND_REG_GPR: + if (Instrux->Operands[i].Info.Register.Reg < 8) + { + *(&Rlut->Rax + Instrux->Operands[i].Info.Register.Reg) = &Instrux->Operands[i]; + } + break; + default: + break; + } + } + } + + return ND_STATUS_SUCCESS; +} \ No newline at end of file diff --git a/bddisasm/include/instructions.h b/bddisasm/include/instructions.h index e476a02..5b41a93 100644 --- a/bddisasm/include/instructions.h +++ b/bddisasm/include/instructions.h @@ -3983,7 +3983,7 @@ const ND_INSTRUCTION gInstructions[2701] = // Pos:239 Instruction:"ERETS" Encoding:"0xF2 0x0F 0x01 /0xCA"/"" { - ND_INS_ERETS, ND_CAT_FRED, ND_SET_FRED, 169, + ND_INS_ERETS, ND_CAT_RET, ND_SET_FRED, 169, 0, ND_MOD_R0|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_VMX_OFF|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX_OFF|ND_MOD_TSX_OFF, 0, ND_OPS_CNT(0, 5), 0, 0, 0, 0, 0, 0, ND_FLAG_F64|ND_FLAG_MODRM|ND_FLAG_O64, ND_CFF_FRED, @@ -4002,7 +4002,7 @@ const ND_INSTRUCTION gInstructions[2701] = // Pos:240 Instruction:"ERETU" Encoding:"0xF3 0x0F 0x01 /0xCA"/"" { - ND_INS_ERETU, ND_CAT_FRED, ND_SET_FRED, 170, + ND_INS_ERETU, ND_CAT_RET, ND_SET_FRED, 170, 0, ND_MOD_R0|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_VMX_OFF|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX_OFF|ND_MOD_TSX_OFF, 0, ND_OPS_CNT(0, 9), 0, 0, 0, 0, 0, 0, ND_FLAG_F64|ND_FLAG_MODRM|ND_FLAG_O64, ND_CFF_FRED, @@ -22273,7 +22273,7 @@ const ND_INSTRUCTION gInstructions[2701] = // Pos:1349 Instruction:"UIRET" Encoding:"0xF3 0x0F 0x01 /0xEC"/"" { - ND_INS_UIRET, ND_CAT_UINTR, ND_SET_UINTR, 810, + ND_INS_UIRET, ND_CAT_RET, ND_SET_UINTR, 810, 0, ND_MOD_R0|ND_MOD_R1|ND_MOD_R2|ND_MOD_R3|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_VMX_OFF|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX_OFF|ND_MOD_TSX_OFF, 0, ND_OPS_CNT(0, 6), 0, 0, 0, 0, 0, 0, ND_FLAG_F64|ND_FLAG_MODRM|ND_FLAG_O64, ND_CFF_UINTR, @@ -30955,7 +30955,7 @@ const ND_INSTRUCTION gInstructions[2701] = { ND_INS_VMCALL, ND_CAT_VTX, ND_SET_VTX, 1160, 0, - ND_MOD_R0|ND_MOD_R1|ND_MOD_R2|ND_MOD_R3|ND_MOD_REAL|ND_MOD_V8086|ND_MOD_PROT|ND_MOD_COMPAT|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX_OFF|ND_MOD_TSX|ND_MOD_TSX_OFF, + ND_MOD_R0|ND_MOD_R1|ND_MOD_R2|ND_MOD_R3|ND_MOD_REAL|ND_MOD_V8086|ND_MOD_PROT|ND_MOD_COMPAT|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX_OFF|ND_MOD_TSX_OFF, 0, ND_OPS_CNT(0, 0), 0, 0, 0, 0, 0, 0, ND_FLAG_MODRM, ND_CFF_VTX, 0, 0, @@ -44744,13 +44744,14 @@ const ND_INSTRUCTION gInstructions[2701] = ND_INS_XABORT, ND_CAT_UNCOND_BR, ND_SET_TSX, 1661, 0, ND_MOD_R0|ND_MOD_R1|ND_MOD_R2|ND_MOD_R3|ND_MOD_REAL|ND_MOD_V8086|ND_MOD_PROT|ND_MOD_COMPAT|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_VMX_OFF|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX|ND_MOD_SGX_OFF|ND_MOD_TSX_OFF, - 0, ND_OPS_CNT(1, 1), 0, 0, 0, 0, 0, 0, ND_FLAG_MODRM, ND_CFF_RTM, + 0, ND_OPS_CNT(1, 2), 0, 0, 0, 0, 0, 0, ND_FLAG_MODRM, ND_CFF_RTM, 0, 0, 0, 0, { OP(ND_OPT_I, ND_OPS_b, 0, ND_OPA_R, 0, 0), + OP(ND_OPT_RIP, ND_OPS_yf, ND_OPF_DEFAULT, ND_OPA_W, 0, 0), OP(ND_OPT_GPR_rAX, ND_OPS_d, ND_OPF_DEFAULT, ND_OPA_RCW, 0, 0), }, }, @@ -45046,13 +45047,13 @@ const ND_INSTRUCTION gInstructions[2701] = ND_INS_XEND, ND_CAT_COND_BR, ND_SET_TSX, 1670, 0, ND_MOD_ANY, - 0, ND_OPS_CNT(0, 0), 0, 0, 0, 0, 0, 0, ND_FLAG_MODRM, ND_CFF_RTM, + 0, ND_OPS_CNT(0, 1), 0, 0, 0, 0, 0, 0, ND_FLAG_MODRM, ND_CFF_RTM, 0, 0, 0, 0, { - 0 + OP(ND_OPT_RIP, ND_OPS_yf, ND_OPF_DEFAULT, ND_OPA_CW, 0, 0), }, }, diff --git a/bddisasm/include/nd_crt.h b/bddisasm/include/nd_crt.h index b1281cd..c95dd66 100644 --- a/bddisasm/include/nd_crt.h +++ b/bddisasm/include/nd_crt.h @@ -12,8 +12,7 @@ #endif #if defined(_MSC_VER) - -typedef char * va_list; +#include # ifndef _ADDRESSOF # ifdef __cplusplus @@ -27,8 +26,6 @@ typedef char * va_list; # if defined(AMD64) || defined(WIN64) -extern void __cdecl __va_start(__out va_list *, ...); // is this exported by VC compiler? - # define _crt_va_start(ap, x) ( __va_start(&ap, x) ) # define _crt_va_arg(ap, t) ( ( sizeof(t) > sizeof(QWORD) || ( sizeof(t) & (sizeof(t) - 1) ) != 0 ) \ ? **(t **)( ( ap += sizeof(QWORD) ) - sizeof(QWORD) ) \ diff --git a/bddisasm_test/basic/tsx_64.result b/bddisasm_test/basic/tsx_64.result index 0b8862f..601852a 100644 --- a/bddisasm_test/basic/tsx_64.result +++ b/bddisasm_test/basic/tsx_64.result @@ -46,7 +46,8 @@ HLE: no, XACQUIRE only: no, XRELEASE only: no BND: no, BHINT: no, DNT: no Operand: 0, Acc: R-, Type: Immediate, Size: 1, RawSize: 1, Encoding: I - Operand: 1, Acc: RCW, Type: Register, Size: 4, RawSize: 4, Encoding: S, RegType: General Purpose, RegSize: 4, RegId: 0, RegCount: 1 + Operand: 1, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: IP, RegSize: 8, RegId: 0, RegCount: 1 + Operand: 2, Acc: RCW, Type: Register, Size: 4, RawSize: 4, Encoding: S, RegType: General Purpose, RegSize: 4, RegId: 0, RegCount: 1 000000000000000C 0f01d5 XEND DSIZE: 32, ASIZE: 64, VLEN: - @@ -61,6 +62,7 @@ REP: no, REPcc: no, LOCK: no HLE: no, XACQUIRE only: no, XRELEASE only: no BND: no, BHINT: no, DNT: no + Operand: 0, Acc: CW, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: IP, RegSize: 8, RegId: 0, RegCount: 1 000000000000000F f20f01e8 XSUSLDTRK DSIZE: 32, ASIZE: 64, VLEN: - diff --git a/bddisasm_test/basic/vmx_64.result b/bddisasm_test/basic/vmx_64.result index ef8a4bd..622bafa 100644 --- a/bddisasm_test/basic/vmx_64.result +++ b/bddisasm_test/basic/vmx_64.result @@ -5,7 +5,7 @@ Valid modes R0: yes, R1: yes, R2: yes, R3: yes Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes - SMM on: yes, SMM off: yes, SGX on: no, SGX off: yes, TSX on: yes, TSX off: yes + SMM on: yes, SMM off: yes, SGX on: no, SGX off: yes, TSX on: no, TSX off: yes VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: no Valid prefixes REP: no, REPcc: no, LOCK: no diff --git a/bddisasm_test/fred/fred_64.result b/bddisasm_test/fred/fred_64.result index 9b1b763..05b03ae 100644 --- a/bddisasm_test/fred/fred_64.result +++ b/bddisasm_test/fred/fred_64.result @@ -1,6 +1,6 @@ 0000000000000000 f30f01ca ERETU DSIZE: 64, ASIZE: 64, VLEN: - - ISA Set: FRED, Ins cat: FRED, CET tracked: no + ISA Set: FRED, Ins cat: RET, CET tracked: no CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 17 FLAGS access Entire register @@ -26,7 +26,7 @@ 0000000000000004 f20f01ca ERETS DSIZE: 64, ASIZE: 64, VLEN: - - ISA Set: FRED, Ins cat: FRED, CET tracked: no + ISA Set: FRED, Ins cat: RET, CET tracked: no CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 17 FLAGS access Entire register diff --git a/bddisasm_test/uintr/uintr_64.result b/bddisasm_test/uintr/uintr_64.result index bda44b5..69081e4 100644 --- a/bddisasm_test/uintr/uintr_64.result +++ b/bddisasm_test/uintr/uintr_64.result @@ -1,6 +1,6 @@ 0000000000000000 f30f01ec UIRET DSIZE: 64, ASIZE: 64, VLEN: - - ISA Set: UINTR, Ins cat: UINTR, CET tracked: no + ISA Set: UINTR, Ins cat: RET, CET tracked: no CPUID leaf: 0x00000007, sub-leaf: 0x00000000, reg: edx, bit: 5 FLAGS access Entire register diff --git a/bindings/pybddisasm/setup.py b/bindings/pybddisasm/setup.py index 7125bb4..1d5834f 100644 --- a/bindings/pybddisasm/setup.py +++ b/bindings/pybddisasm/setup.py @@ -12,7 +12,7 @@ from setuptools import find_packages, setup, Command, Extension, Distribution from codecs import open VERSION = (0, 1, 3) -LIBRARY_VERSION = (1, 34, 5) +LIBRARY_VERSION = (1, 34, 7) LIBRARY_INSTRUX_SIZE = 864 packages = ['pybddisasm'] diff --git a/inc/bddisasm.h b/inc/bddisasm.h index 8928f3f..e4400d3 100644 --- a/inc/bddisasm.h +++ b/inc/bddisasm.h @@ -669,35 +669,6 @@ typedef enum _ND_EX_TYPE_AMX } ND_EX_TYPE_AMX; -// -// Operands access map. Contains every register except for MSR & XCR, includes memory, flags, RIP, stack. -// Use NdGetFullAccessMap to populate this structure. -// -typedef struct _ND_ACCESS_MAP -{ - uint8_t RipAccess; - uint8_t FlagsAccess; - uint8_t StackAccess; - uint8_t MemAccess; - uint8_t MxcsrAccess; - uint8_t PkruAccess; - uint8_t SspAccess; - uint8_t GprAccess[ND_MAX_GPR_REGS]; - uint8_t SegAccess[ND_MAX_SEG_REGS]; - uint8_t FpuAccess[ND_MAX_FPU_REGS]; - uint8_t MmxAccess[ND_MAX_MMX_REGS]; - uint8_t SseAccess[ND_MAX_SSE_REGS]; - uint8_t CrAccess [ND_MAX_CR_REGS ]; - uint8_t DrAccess [ND_MAX_DR_REGS ]; - uint8_t TrAccess [ND_MAX_TR_REGS ]; - uint8_t BndAccess[ND_MAX_BND_REGS]; - uint8_t MskAccess[ND_MAX_MSK_REGS]; - uint8_t SysAccess[ND_MAX_SYS_REGS]; - uint8_t X87Access[ND_MAX_X87_REGS]; -} ND_ACCESS_MAP, *PND_ACCESS_MAP; - - - // // Operand access mode. // @@ -1231,6 +1202,18 @@ typedef struct _ND_FPU_FLAGS } ND_FPU_FLAGS, *PND_FPU_FLAGS; +// +// Branch information. +// +typedef struct _ND_BRANCH_INFO +{ + uint8_t IsBranch : 1; + uint8_t IsConditional : 1; + uint8_t IsIndirect : 1; + uint8_t IsFar : 1; +} ND_BRANCH_INFO; + + // // Describes a decoded instruction. All the possible information about the instruction is contained in this structure. // You don't have to call any other APIs to gather any more info about it. @@ -1394,10 +1377,13 @@ typedef struct _INSTRUX ND_OPERAND Operands[ND_MAX_OPERAND]; // Instruction operands. // As extracted from the operands themselves. + uint8_t CsAccess; // CS access mode (read/write). Includes only implicit CS accesses. uint8_t RipAccess; // RIP access mode (read/write). uint8_t StackAccess; // Stack access mode (push/pop). uint8_t MemoryAccess; // Memory access mode (read/write, including stack or shadow stack). + ND_BRANCH_INFO BranchInfo; // Branch information. + struct { uint8_t RegAccess; // RFLAGS access mode (read/write), as per the entire register. @@ -1429,11 +1415,9 @@ typedef struct _INSTRUX ND_VALID_MODES ValidModes; // Valid CPU modes for the instruction. ND_VALID_PREFIXES ValidPrefixes; // Indicates which prefixes are valid for this instruction. ND_VALID_DECORATORS ValidDecorators; // What decorators are accepted by the instruction. - uint8_t Reserved1[3]; // Padding purpose. Aligns the mnemonic to 8 bytes. char Mnemonic[ND_MAX_MNEMONIC_LENGTH]; // Instruction mnemonic. uint8_t OpCodeBytes[3]; // Opcode bytes - escape codes and main op code uint8_t PrimaryOpCode; // Main/nominal opcode - uint32_t Reserved2; // Padding purpose. Aligns the InstructionBytes to 16 bytes. uint8_t InstructionBytes[16]; // The entire instruction. } INSTRUX, *PINSTRUX; @@ -1454,6 +1438,76 @@ typedef struct _ND_CONTEXT } ND_CONTEXT; +// +// Operands access map. Contains every register except for MSR & XCR, includes memory, flags, RIP, stack. +// Use NdGetFullAccessMap to populate this structure. +// +typedef struct _ND_ACCESS_MAP +{ + uint8_t RipAccess; + uint8_t FlagsAccess; + uint8_t StackAccess; + uint8_t MemAccess; + uint8_t MxcsrAccess; + uint8_t PkruAccess; + uint8_t SspAccess; + uint8_t GprAccess[ND_MAX_GPR_REGS]; + uint8_t SegAccess[ND_MAX_SEG_REGS]; + uint8_t FpuAccess[ND_MAX_FPU_REGS]; + uint8_t MmxAccess[ND_MAX_MMX_REGS]; + uint8_t SseAccess[ND_MAX_SSE_REGS]; + uint8_t CrAccess [ND_MAX_CR_REGS ]; + uint8_t DrAccess [ND_MAX_DR_REGS ]; + uint8_t TrAccess [ND_MAX_TR_REGS ]; + uint8_t BndAccess[ND_MAX_BND_REGS]; + uint8_t MskAccess[ND_MAX_MSK_REGS]; + uint8_t TmmAccess[ND_MAX_TILE_REGS]; + uint8_t SysAccess[ND_MAX_SYS_REGS]; + uint8_t X87Access[ND_MAX_X87_REGS]; +} ND_ACCESS_MAP, *PND_ACCESS_MAP; + + +// +// Operand reverse-lookup table. Each entry inside this structure contains the pointer to the relevant operand. +// Some rules govern this special structure: +// - It is not generated by default. The user must call NdGetOperandRlut manually to fill in this structure. +// - This structure holds pointers inside the INSTRUX provided to the NdGetOperandRlut function; please make sure +// you call NdGetOperandRlut again if the INSTRUX is relocated, as all the pointers will dangle. +// - Not all the operand types have a corresponding entry in ND_OPERAND_RLUT, only the usual ones. +// - Some operands may have multiple entries in ND_OPERAND_RLUT - for example, RMW (read-modify-write) instructions +// will have Dst1 and Src1 pointing to the same operand. +// - The implicit registers entries in ND_OPERAND_RLUT will point to the operand which is of that type, and implicit; +// for example, ND_OPERAND_RLUT.Rax will be NULL for `add rax, rcx`, since in this case, `rax` is not an implicit +// operand. For `cpuid`, however, ND_OPERAND_RLUT.Rax will point to the implicit `eax` register. +// Use NdGetOperandRlut to populate this structure. +// +typedef struct _ND_OPERAND_RLUT +{ + PND_OPERAND Dst1; // First destination operand. + PND_OPERAND Dst2; // Second destination operand. + PND_OPERAND Src1; // First source operand. + PND_OPERAND Src2; // Second source operand. + PND_OPERAND Src3; // Third source operand. + PND_OPERAND Src4; // Fourth source operand. + PND_OPERAND Mem1; // First memory operand. + PND_OPERAND Mem2; // Second memory operand. + PND_OPERAND Stack; // Stack operand. + PND_OPERAND Flags; // Flags register operand. + PND_OPERAND Rip; // Instruction Pointer register operand. + PND_OPERAND Cs; // Implicit CS operand. + PND_OPERAND Ss; // Implicit SS operand. + PND_OPERAND Rax; // Implicit accumulator register operand. + PND_OPERAND Rcx; // Implicit counter register operand. + PND_OPERAND Rdx; // Implicit data register operand + PND_OPERAND Rbx; // Implicit base address register operand. + PND_OPERAND Rsp; // Implicit stack pointer operand. + PND_OPERAND Rbp; // Implicit base pointer operand. + PND_OPERAND Rsi; // Implicit source index operand. + PND_OPERAND Rdi; // Implicit destination index operand. +} ND_OPERAND_RLUT; + + + #ifdef __cplusplus extern "C" { #endif @@ -1560,6 +1614,15 @@ NdGetFullAccessMap( ND_ACCESS_MAP *AccessMap ); +// +// Returns an operand reverse-lookup. One can use the Rlut to quickly reference different kinds of operands in INSTRUX. +// +NDSTATUS +NdGetOperandRlut( + INSTRUX *Instrux, + ND_OPERAND_RLUT *Rlut + ); + // // Initialize the decoder context. // diff --git a/inc/constants.h b/inc/constants.h index d0df420..df0c062 100644 --- a/inc/constants.h +++ b/inc/constants.h @@ -1758,7 +1758,6 @@ typedef enum _ND_INS_TYPE ND_CAT_EXPAND, ND_CAT_FLAGOP, ND_CAT_FMA4, - ND_CAT_FRED, ND_CAT_GATHER, ND_CAT_GFNI, ND_CAT_HRESET, diff --git a/inc/version.h b/inc/version.h index 48c1909..a29ad5d 100644 --- a/inc/version.h +++ b/inc/version.h @@ -7,6 +7,6 @@ #define DISASM_VERSION_MAJOR 1 #define DISASM_VERSION_MINOR 34 -#define DISASM_VERSION_REVISION 5 +#define DISASM_VERSION_REVISION 7 #endif // DISASM_VER_H diff --git a/isagenerator/instructions/table_0F.dat b/isagenerator/instructions/table_0F.dat index 93cd187..ae0b214 100644 --- a/isagenerator/instructions/table_0F.dat +++ b/isagenerator/instructions/table_0F.dat @@ -22,7 +22,7 @@ LMSW Ew CR0 [ 0x0F 0x01 /6 INVLPG Mb nil [ 0x0F 0x01 /7:mem] s:I486REAL, t:SYSTEM, w:R, a:AG, m:KERNEL|NOV86 RSTORSSP Mq SSP [ 0xF3 0x0F 0x01 /5:mem] s:CET_SS, t:CET, a:SHS, w:RW|RW, f:CF=m|ZF=0|PF=0|AF=0|OF=0|SF=0 ENCLV nil EAX,RBX,RCX,RDX [ NP 0x0F 0x01 /0xC0] s:SGX, t:SGX, w:R|CRW|CRW|CRW, m:KERNEL|NOSMM|NOTSX|VMX -VMCALL nil nil [ NP 0x0F 0x01 /0xC1] s:VTX, t:VTX, m:VMX|NOSGX +VMCALL nil nil [ NP 0x0F 0x01 /0xC1] s:VTX, t:VTX, m:VMX|NOTSX|NOSGX VMLAUNCH nil Fv [ NP 0x0F 0x01 /0xC2] s:VTX, t:VTX, w:W, f:VMX, m:VMXROOT VMRESUME nil Fv [ NP 0x0F 0x01 /0xC3] s:VTX, t:VTX, w:W, f:VMX, m:VMXROOT VMXOFF nil Fv [ NP 0x0F 0x01 /0xC4] s:VTX, t:VTX, w:W, f:VMX, m:VMXROOT @@ -30,8 +30,8 @@ PCONFIG nil EAX,RBX,RCX,RDX [ NP 0x0F 0x01 /0 MONITOR nil pAXb,ECX,EDX [ NP 0x0F 0x01 /0xC8] s:SSE3, t:MISC, w:R|R|R, i:MONITOR, m:KERNEL|NOV86 MWAIT nil EAX,ECX [ NP 0x0F 0x01 /0xC9] s:SSE3, t:MISC, w:RW|R, i:MONITOR, m:KERNEL|NOV86 CLAC nil Fv [ NP 0x0F 0x01 /0xCA] s:SMAP, t:SMAP, w:W, f:AC=0, m:KERNEL|NOV86 -ERETU nil rIP,Fv,rSP,CS,SS,Kv5,SSP,GSBASE,KGSBASE [0xF3 0x0F 0x01 /0xCA] s:FRED, t:FRED, w:W|W|W|W|W|R|CRCW|RW|RW, m:KERNEL|O64|NOTSX, a:F64 -ERETS nil rIP,Fv,rSP,Kv5,SSP [ 0xF2 0x0F 0x01 /0xCA] s:FRED, t:FRED, w:W|W|W|R|CRCW, m:KERNEL|O64|NOTSX, a:F64 +ERETU nil rIP,Fv,rSP,CS,SS,Kv5,SSP,GSBASE,KGSBASE [0xF3 0x0F 0x01 /0xCA] s:FRED, t:RET, w:W|W|W|W|W|R|CRCW|RW|RW, m:KERNEL|O64|NOTSX, a:F64 +ERETS nil rIP,Fv,rSP,Kv5,SSP [ 0xF2 0x0F 0x01 /0xCA] s:FRED, t:RET, w:W|W|W|R|CRCW, m:KERNEL|O64|NOTSX, a:F64 STAC nil Fv [ NP 0x0F 0x01 /0xCB] s:SMAP, t:SMAP, w:W, f:AC=1, m:KERNEL|NOV86 TDCALL nil nil [ 0x66 0x0F 0x01 /0xCC] s:TDX, t:TDX, m:KERNEL|VMXNROOT SEAMRET nil nil [ 0x66 0x0F 0x01 /0xCD] s:TDX, t:TDX, f:VMX, m:SEAMR @@ -41,7 +41,7 @@ ENCLS nil EAX,RBX,RCX,RDX [ NP 0x0F 0x01 /0 XGETBV nil ECX,EDX,EAX,XCR [ NP 0x0F 0x01 /0xD0] s:XSAVE, t:XSAVE, w:R|W|W|R XSETBV nil ECX,EDX,EAX,XCR [ NP 0x0F 0x01 /0xD1] s:XSAVE, t:XSAVE, w:R|R|R|W, m:KERNEL VMFUNC nil nil [ NP 0x0F 0x01 /0xD4] s:VTX, t:VTX, m:VMX|NOSGX -XEND nil nil [ NP 0x0F 0x01 /0xD5] s:TSX, t:COND_BR, i:RTM +XEND nil yIP [ NP 0x0F 0x01 /0xD5] s:TSX, t:COND_BR, w:CW, i:RTM XTEST nil Fv [ NP 0x0F 0x01 /0xD6] s:TSX, t:LOGIC, w:W, i:RTM, f:CF=0|PF=0|AF=0|ZF=m|SF=0|OF=0 ENCLU nil EAX,RBX,RCX,RDX [ NP 0x0F 0x01 /0xD7] s:SGX, t:SGX, w:R|CRW|CRW|CRW, m:USER|NOSMM|NOTSX VMRUN nil rAX [ 0x0F 0x01 /0xD8] s:SVM, t:SYSTEM, w:R, m:VMXROOT @@ -60,7 +60,7 @@ SETSSBSY nil SHS0,SSP [ 0xF3 0x0F 0x01 /0 XSUSLDTRK nil nil [ 0xF2 0x0F 0x01 /0xE8] s:TSXLDTRK, t:MISC XRESLDTRK nil nil [ 0xF2 0x0F 0x01 /0xE9] s:TSXLDTRK, t:MISC SAVEPREVSSP nil SHSS,SSP [ 0xF3 0x0F 0x01 /0xEA] s:CET_SS, t:CET, w:RW|R, f:CF=t -UIRET nil rIP,Fv,sSP,UIF,Kv3,SHS1 [ 0xF3 0x0F 0x01 /0xEC] s:UINTR, t:UINTR, a:F64, w:W|W|W|W|R|R, m:O64|NOTSX|NOSGX +UIRET nil rIP,Fv,sSP,UIF,Kv3,SHS1 [ 0xF3 0x0F 0x01 /0xEC] s:UINTR, t:RET, a:F64, w:W|W|W|W|R|R, m:O64|NOTSX|NOSGX TESTUI nil UIF,Fv [ 0xF3 0x0F 0x01 /0xED] s:UINTR, t:UINTR, w:R|W, f:UINTR, m:O64|NOSGX RDPKRU nil EDX,EAX,ECX,PKRU [ NP 0x0F 0x01 /0xEE] s:PKU, t:MISC, w:W|W|R|R CLUI nil UIF [ 0xF3 0x0F 0x01 /0xEE] s:UINTR, t:UINTR, w:W, m:O64|NOTSX|NOSGX diff --git a/isagenerator/instructions/table_base.dat b/isagenerator/instructions/table_base.dat index 20faaa7..9bb00a9 100644 --- a/isagenerator/instructions/table_base.dat +++ b/isagenerator/instructions/table_base.dat @@ -331,7 +331,7 @@ RETN nil rIP,Kv,SHS1 [ 0xC3] s:I86 LES Gz,Mp ES [ 0xC4 /r:mem] s:I86, t:SEGOP, w:W|R|W, m:NO64|NOSGX LDS Gz,Mp DS [ 0xC5 /r:mem] s:I86, t:SEGOP, w:W|R|W, m:NO64|NOSGX MOV Eb,Ib nil [ 0xC6 /0 ib] s:I86, t:DATAXFER, w:W|R, p:XRELEASE|HLEWOL -XABORT Ib EAX [ 0xC6 /0xF8 ib] s:TSX, t:UNCOND_BR, w:R|RCW, i:RTM, m:NOTSX +XABORT Ib yIP,EAX [ 0xC6 /0xF8 ib] s:TSX, t:UNCOND_BR, w:R|W|RCW, i:RTM MOV Ev,Iz nil [ 0xC7 /0 iz] s:I86, t:DATAXFER, w:W|R, a:OP2SEXO1, p:XRELEASE|HLEWOL XBEGIN Jz yIP,EAX [ 0xC7 /0xF8 cz] s:TSX, t:COND_BR, w:R|RCW|CW, i:RTM ENTER Iw,Ib rBP,sSP,Kv [ 0xC8 iw ib] s:I186, t:MISC, w:R|R|RW|RW|W, a:D64