Implemented a reverse oprand lookup table. It holds pointers to relevant operands inside INSTRUX, for quick lookup.
Moved helper functions in bdhelpers.c. Added a dedicated BranchInfo field inside INSTRUX, containing the most relevant branch information.pull/53/head
parent
def76f8633
commit
433e723e07
@ -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;
|
||||||
|
}
|
Loading…
Reference in new issue