📄 toir.c
字号:
#define OFFB_XMM9 offsetof(VexGuestAMD64State,guest_XMM9)#define OFFB_XMM10 offsetof(VexGuestAMD64State,guest_XMM10)#define OFFB_XMM11 offsetof(VexGuestAMD64State,guest_XMM11)#define OFFB_XMM12 offsetof(VexGuestAMD64State,guest_XMM12)#define OFFB_XMM13 offsetof(VexGuestAMD64State,guest_XMM13)#define OFFB_XMM14 offsetof(VexGuestAMD64State,guest_XMM14)#define OFFB_XMM15 offsetof(VexGuestAMD64State,guest_XMM15)#define OFFB_EMWARN offsetof(VexGuestAMD64State,guest_EMWARN)#define OFFB_TISTART offsetof(VexGuestAMD64State,guest_TISTART)#define OFFB_TILEN offsetof(VexGuestAMD64State,guest_TILEN)#define OFFB_NRADDR offsetof(VexGuestAMD64State,guest_NRADDR)/*------------------------------------------------------------*//*--- Helper bits and pieces for deconstructing the ---*//*--- amd64 insn stream. ---*//*------------------------------------------------------------*//* This is the AMD64 register encoding -- integer regs. */#define R_RAX 0#define R_RCX 1#define R_RDX 2#define R_RBX 3#define R_RSP 4#define R_RBP 5#define R_RSI 6#define R_RDI 7#define R_R8 8#define R_R9 9#define R_R10 10#define R_R11 11#define R_R12 12#define R_R13 13#define R_R14 14#define R_R15 15//.. #define R_AL (0+R_EAX)//.. #define R_AH (4+R_EAX)/* This is the Intel register encoding -- segment regs. */#define R_ES 0#define R_CS 1#define R_SS 2#define R_DS 3#define R_FS 4#define R_GS 5/* Various simple conversions */static ULong extend_s_8to64 ( UChar x ){ return (ULong)((((Long)x) << 56) >> 56);}static ULong extend_s_16to64 ( UShort x ){ return (ULong)((((Long)x) << 48) >> 48);}static ULong extend_s_32to64 ( UInt x ){ return (ULong)((((Long)x) << 32) >> 32);}/* Figure out whether the mod and rm parts of a modRM byte refer to a register or memory. If so, the byte will have the form 11XXXYYY, where YYY is the register number. */inlinestatic Bool epartIsReg ( UChar mod_reg_rm ){ return toBool(0xC0 == (mod_reg_rm & 0xC0));}/* Extract the 'g' field from a modRM byte. This only produces 3 bits, which is not a complete register number. You should avoid this function if at all possible. */inlinestatic Int gregLO3ofRM ( UChar mod_reg_rm ){ return (Int)( (mod_reg_rm >> 3) & 7 );}/* Ditto the 'e' field of a modRM byte. */inlinestatic Int eregLO3ofRM ( UChar mod_reg_rm ){ return (Int)(mod_reg_rm & 0x7);}/* Get a 8/16/32-bit unsigned value out of the insn stream. */static UChar getUChar ( Long delta ){ UChar v = guest_code[delta+0]; return v;}//.. static UInt getUDisp16 ( Long delta )//.. {//.. UInt v = guest_code[delta+1]; v <<= 8;//.. v |= guest_code[delta+0];//.. return v & 0xFFFF;//.. }//.. //.. static UInt getUDisp ( Int size, Long delta )//.. {//.. switch (size) {//.. case 4: return getUDisp32(delta);//.. case 2: return getUDisp16(delta);//.. case 1: return getUChar(delta);//.. default: vpanic("getUDisp(x86)");//.. }//.. return 0; /*notreached*///.. }/* Get a byte value out of the insn stream and sign-extend to 64 bits. */static Long getSDisp8 ( Long delta ){ return extend_s_8to64( guest_code[delta] );}/* Get a 16-bit value out of the insn stream and sign-extend to 64 bits. */static Long getSDisp16 ( Long delta ){ UInt v = guest_code[delta+1]; v <<= 8; v |= guest_code[delta+0]; return extend_s_16to64( (UShort)v );}/* Get a 32-bit value out of the insn stream and sign-extend to 64 bits. */static Long getSDisp32 ( Long delta ){ UInt v = guest_code[delta+3]; v <<= 8; v |= guest_code[delta+2]; v <<= 8; v |= guest_code[delta+1]; v <<= 8; v |= guest_code[delta+0]; return extend_s_32to64( v );}/* Get a 64-bit value out of the insn stream. */static Long getDisp64 ( Long delta ){ ULong v = 0; v |= guest_code[delta+7]; v <<= 8; v |= guest_code[delta+6]; v <<= 8; v |= guest_code[delta+5]; v <<= 8; v |= guest_code[delta+4]; v <<= 8; v |= guest_code[delta+3]; v <<= 8; v |= guest_code[delta+2]; v <<= 8; v |= guest_code[delta+1]; v <<= 8; v |= guest_code[delta+0]; return v;}/* Note: because AMD64 doesn't allow 64-bit literals, it is an error if this is called with size==8. Should not happen. */static Long getSDisp ( Int size, Long delta ){ switch (size) { case 4: return getSDisp32(delta); case 2: return getSDisp16(delta); case 1: return getSDisp8(delta); default: vpanic("getSDisp(amd64)"); }}static ULong mkSizeMask ( Int sz ){ switch (sz) { case 1: return 0x00000000000000FFULL; case 2: return 0x000000000000FFFFULL; case 4: return 0x00000000FFFFFFFFULL; case 8: return 0xFFFFFFFFFFFFFFFFULL; default: vpanic("mkSzMask(amd64)"); }}static Int imin ( Int a, Int b ){ return (a < b) ? a : b;}static IRType szToITy ( Int n ){ switch (n) { case 1: return Ity_I8; case 2: return Ity_I16; case 4: return Ity_I32; case 8: return Ity_I64; default: vex_printf("\nszToITy(%d)\n", n); vpanic("szToITy(amd64)"); }}/*------------------------------------------------------------*//*--- For dealing with prefixes. ---*//*------------------------------------------------------------*//* The idea is to pass around an int holding a bitmask summarising info from the prefixes seen on the current instruction, including info from the REX byte. This info is used in various places, but most especially when making sense of register fields in instructions. The top 16 bits of the prefix are 0x3141, just as a hacky way to ensure it really is a valid prefix. Things you can safely assume about a well-formed prefix: * at most one segment-override bit (CS,DS,ES,FS,GS,SS) is set. * if REX is not present then REXW,REXR,REXX,REXB will read as zero. * F2 and F3 will not both be 1.*/typedef UInt Prefix;#define PFX_ASO (1<<0) /* address-size override present (0x67) */#define PFX_66 (1<<1) /* operand-size override-to-16 present (0x66) */#define PFX_REX (1<<2) /* REX byte present (0x40 to 0x4F) */#define PFX_REXW (1<<3) /* REX W bit, if REX present, else 0 */#define PFX_REXR (1<<4) /* REX R bit, if REX present, else 0 */#define PFX_REXX (1<<5) /* REX X bit, if REX present, else 0 */#define PFX_REXB (1<<6) /* REX B bit, if REX present, else 0 */#define PFX_LOCK (1<<7) /* bus LOCK prefix present (0xF0) */#define PFX_F2 (1<<8) /* REP/REPE/REPZ prefix present (0xF2) */#define PFX_F3 (1<<9) /* REPNE/REPNZ prefix present (0xF3) */#define PFX_CS (1<<10) /* CS segment prefix present (0x2E) */#define PFX_DS (1<<11) /* DS segment prefix present (0x3E) */#define PFX_ES (1<<12) /* ES segment prefix present (0x26) */#define PFX_FS (1<<13) /* FS segment prefix present (0x64) */#define PFX_GS (1<<14) /* GS segment prefix present (0x65) */#define PFX_SS (1<<15) /* SS segment prefix present (0x36) */#define PFX_EMPTY 0x31410000static Bool IS_VALID_PFX ( Prefix pfx ) { return toBool((pfx & 0xFFFF0000) == PFX_EMPTY);}static Bool haveREX ( Prefix pfx ) { return toBool(pfx & PFX_REX);}static Int getRexW ( Prefix pfx ) { return (pfx & PFX_REXW) ? 1 : 0;}/* Apparently unused.static Int getRexR ( Prefix pfx ) { return (pfx & PFX_REXR) ? 1 : 0;}*/static Int getRexX ( Prefix pfx ) { return (pfx & PFX_REXX) ? 1 : 0;}static Int getRexB ( Prefix pfx ) { return (pfx & PFX_REXB) ? 1 : 0;}/* Check a prefix doesn't have F2 or F3 set in it, since usually that completely changes what instruction it really is. */static Bool haveF2orF3 ( Prefix pfx ) { return toBool((pfx & (PFX_F2|PFX_F3)) > 0);}static Bool haveF2 ( Prefix pfx ) { return toBool((pfx & PFX_F2) > 0);}static Bool haveF3 ( Prefix pfx ) { return toBool((pfx & PFX_F3) > 0);}static Bool have66 ( Prefix pfx ) { return toBool((pfx & PFX_66) > 0);}static Bool haveASO ( Prefix pfx ) { return toBool((pfx & PFX_ASO) > 0);}/* Return True iff pfx has 66 set and F2 and F3 clear */static Bool have66noF2noF3 ( Prefix pfx ){ return toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_66);}/* Return True iff pfx has F2 set and 66 and F3 clear */static Bool haveF2no66noF3 ( Prefix pfx ){ return toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_F2);}/* Return True iff pfx has F3 set and 66 and F2 clear */static Bool haveF3no66noF2 ( Prefix pfx ){ return toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == PFX_F3);}/* Return True iff pfx has 66, F2 and F3 clear */static Bool haveNo66noF2noF3 ( Prefix pfx ){ return toBool((pfx & (PFX_66|PFX_F2|PFX_F3)) == 0);}/* Return True iff pfx has any of 66, F2 and F3 set */static Bool have66orF2orF3 ( Prefix pfx ){ return toBool( ! haveNo66noF2noF3(pfx) );}/* Clear all the segment-override bits in a prefix. */static Prefix clearSegBits ( Prefix p ){ return p & ~(PFX_CS | PFX_DS | PFX_ES | PFX_FS | PFX_GS | PFX_SS);}/*------------------------------------------------------------*//*--- For dealing with integer registers ---*//*------------------------------------------------------------*//* This is somewhat complex. The rules are: For 64, 32 and 16 bit register references, the e or g fields in the modrm bytes supply the low 3 bits of the register number. The fourth (most-significant) bit of the register number is supplied by the REX byte, if it is present; else that bit is taken to be zero. The REX.R bit supplies the high bit corresponding to the g register field, and the REX.B bit supplies the high bit corresponding to the e register field (when the mod part of modrm indicates that modrm's e component refers to a register and not to memory). The REX.X bit supplies a high register bit for certain registers in SIB address modes, and is generally rarely used. For 8 bit register references, the presence of the REX byte itself has significance. If there is no REX present, then the 3-bit number extracted from the modrm e or g field is treated as an index into the sequence %al %cl %dl %bl %ah %ch %dh %bh -- that is, the old x86 encoding scheme. But if there is a REX present, the register reference is interpreted in the same way as for 64/32/16-bit references: a high bit is extracted from REX, giving a 4-bit number, and the denoted register is the lowest 8 bits of the 16 integer registers denoted by the number. In particular, values 3 through 7 of this sequence do not refer to %ah %ch %dh %bh but instead to the lowest 8 bits of %rsp %rbp %rsi %rdi. The REX.W bit has no bearing at all on register numbers. Instead its presence indicates that the operand size is to be overridden from its default value (32 bits) to 64 bits instead. This is in the same fashion that an 0x66 prefix indicates the operand size is to be overridden from 32 bits down to 16 bits. When both REX.W and 0x66 are present there is a conflict, and REX.W takes precedence. Rather than try to handle this complexity using a single huge function, several smaller ones are provided. The aim is to make it as difficult as possible to screw up register decoding in a subtle and hard-to-track-down way. Because these routines fish around in the host's memory (that is, in the guest state area) for sub-parts of guest registers, their correctness depends on the host's endianness. So far these routines only work for little-endian hosts. Those for which endianness is important have assertions to ensure sanity.*//* About the simplest question you can ask: where do the 64-bit integer registers live (in the guest state) ? */static Int integerGuestReg64Offset ( UInt reg ){ switch (reg) { case R_RAX: return OFFB_RAX; case R_RCX: return OFFB_RCX; case R_RDX: return OFFB_RDX; case R_RBX: return OFFB_RBX; case R_RSP: return OFFB_RSP; case R_RBP: return OFFB_RBP; case R_RSI: return OFFB_RSI; case R_RDI: return OFFB_RDI; case R_R8: return OFFB_R8; case R_R9: return OFFB_R9; case R_R10: return OFFB_R10; case R_R11: return OFFB_R11; case R_R12: return OFFB_R12; case R_R13: return OFFB_R13; case R_R14: return OFFB_R14; case R_R15: return OFFB_R15; default: vpanic("integerGuestReg64Offset(amd64)"); }}/* Produce the name of an integer register, for printing purposes. reg is a number in the range 0 .. 15 that has been generated from a 3-bit reg-field number and a REX extension bit. irregular denotes the case where sz==1 and no REX byte is present. */static HChar* nameIReg ( Int sz, UInt reg, Bool irregular ){ static HChar* ireg64_names[16]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -