Package envi :: Package archs :: Package amd64 :: Module disasm
[hide private]
[frames] | no frames]

Source Code for Module envi.archs.amd64.disasm

  1  import envi 
  2  import envi.bits as e_bits 
  3  import envi.archs.i386 as e_i386 
  4  import envi.archs.i386.opcode86 as opcode86 
  5  
 
  6  from envi.archs.amd64.regs import * 
  7  
 
  8  # Pre generate these for fast lookup. Because our REX prefixes have the same relative
 
  9  # bit relationship to eachother, we can cheat a little...
 
 10  amd64_prefixes = list(e_i386.i386_prefixes) 
 11  amd64_prefixes[0x40] = (0x10 << 16) 
 12  amd64_prefixes[0x41] = (0x11 << 16) 
 13  amd64_prefixes[0x42] = (0x12 << 16) 
 14  amd64_prefixes[0x43] = (0x13 << 16) 
 15  amd64_prefixes[0x44] = (0x14 << 16) 
 16  amd64_prefixes[0x45] = (0x15 << 16) 
 17  amd64_prefixes[0x46] = (0x16 << 16) 
 18  amd64_prefixes[0x47] = (0x17 << 16) 
 19  amd64_prefixes[0x48] = (0x18 << 16) 
 20  amd64_prefixes[0x49] = (0x19 << 16) 
 21  amd64_prefixes[0x4a] = (0x1a << 16) 
 22  amd64_prefixes[0x4b] = (0x1b << 16) 
 23  amd64_prefixes[0x4c] = (0x1c << 16) 
 24  amd64_prefixes[0x4d] = (0x1d << 16) 
 25  amd64_prefixes[0x4e] = (0x1e << 16) 
 26  amd64_prefixes[0x4f] = (0x1f << 16) 
 27  
 
 28  # NOTE: some notes from the intel manual...
 
 29  # REX.W overrides 66, but alternate registers (via REX.B etc..) can have 66 to be 16 bit..
 
 30  # REX.R only modifies reg for GPR/SSE(SIMD)/ctrl/debug addressing modes.
 
 31  # REX.X only modifies the SIB index value
 
 32  # REX.B modifies modrm r/m field, or SIB base (if SIB present), or opcode reg.
 
 33  # We inherit all the regular intel prefixes...
 
 34  PREFIX_REX   = 0x100000 # Shows that the rex prefix is present 
 35  PREFIX_REX_B = 0x010000 # Bit 0 in REX prefix (0x41) means ModR/M r/m field, SIB base, or opcode reg 
 36  PREFIX_REX_X = 0x020000 # Bit 1 in REX prefix (0x42) means SIB index extension 
 37  PREFIX_REX_R = 0x040000 # Bit 2 in REX prefix (0x44) means ModR/M reg extention 
 38  PREFIX_REX_W = 0x080000 # Bit 3 in REX prefix (0x48) means 64 bit operand 
 39  
 
 40  REX_BUMP = 8 
 41  MODE_16 = 0 
 42  MODE_32 = 1 
 43  MODE_64 = 2 
 44  
 
45 -class Amd64RipRelOper(envi.DerefOper):
46 - def __init__(self, imm, tsize):
47 self.imm = imm 48 self.tsize = tsize 49 self._is_deref = True
50
51 - def getOperValue(self, op, emu=None):
52 if self._is_deref == False: # Special lea behavior 53 return self.getOperAddr(op) 54 if emu == None: return None 55 return emu.readMemValue(self.getOperAddr(op, emu), self.tsize)
56
57 - def setOperValue(self, op, emu, val):
58 emu.writeMemValue(self.getOperAddr(op, emu), val, self.tsize)
59
60 - def getOperAddr(self, op, emu=None):
61 return op.va + op.size + self.imm
62
63 - def isDeref(self):
64 # The disassembler may reach in and set this (if lea...) 65 return self._is_deref
66
67 - def render(self, mcanv, op, idx):
68 destva = op.va + op.size + self.imm 69 sym = mcanv.syms.getSymByAddr(destva) 70 71 mcanv.addNameText(e_i386.sizenames[self.tsize]) 72 mcanv.addText(" [") 73 mcanv.addNameText("rip", typename="registers") 74 75 if self.imm > 0: 76 mcanv.addText(" + ") 77 if sym != None: 78 mcanv.addVaText("$%s" % repr(sym), destva) 79 else: 80 mcanv.addNameText(str(self.imm)) 81 elif self.imm < 0: 82 mcanv.addText(" - ") 83 if sym != None: 84 mcanv.addVaText("$%s" % repr(sym), destva) 85 else: 86 mcanv.addNameText(str(abs(self.imm))) 87 mcanv.addText("]")
88
89 - def repr(self, op):
90 return "[rip + %d]" % self.imm
91
92 -class Amd64Disasm(e_i386.i386Disasm):
93
94 - def __init__(self):
95 e_i386.i386Disasm.__init__(self) 96 self._dis_prefixes = amd64_prefixes 97 self._dis_regctx = Amd64RegisterContext() 98 99 # Over-ride these which are in use by the i386 version of the ASM 100 self.ROFFSET_MMX = e_i386.getRegOffset(amd64regs, "mm0") 101 self.ROFFSET_SIMD = e_i386.getRegOffset(amd64regs, "xmm0") 102 self.ROFFSET_DEBUG = e_i386.getRegOffset(amd64regs, "debug0") 103 self.ROFFSET_CTRL = e_i386.getRegOffset(amd64regs, "ctrl0") 104 self.ROFFSET_TEST = e_i386.getRegOffset(amd64regs, "test0") 105 self.ROFFSET_SEG = e_i386.getRegOffset(amd64regs, "es") 106 self.ROFFSET_FPU = e_i386.getRegOffset(amd64regs, "st0")
107 108 # NOTE: Technically, the REX must be the *last* prefix specified 109
110 - def _dis_calc_tsize(self, opertype, prefixes):
111 """ 112 Use the oper type and prefixes to decide on the tsize for 113 the operand. 114 """ 115 116 mode = MODE_32 117 118 sizelist = opcode86.OPERSIZE.get(opertype, None) 119 if sizelist == None: 120 raise "OPERSIZE FAIL" 121 122 # NOTE: REX takes precedence over 66 123 # (see section 2.2.1.2 in Intel 2a) 124 if prefixes & PREFIX_REX_W: 125 126 mode = MODE_64 127 128 elif prefixes & e_i386.PREFIX_OP_SIZE: 129 130 mode = MODE_16 131 132 return sizelist[mode]
133
134 - def byteRegOffset(self, val):
135 # NOTE: Override this because there is no AH etc in 64 bit mode 136 return val + e_i386.RMETA_LOW8
137
138 - def extended_parse_modrm(self, bytes, offset, opersize, regbase=0):
139 """ 140 Return a tuple of (size, Operand) 141 """ 142 size = 1 143 # FIXME this would be best to not parse_modrm twice. tweak it. 144 mod,reg,rm = self.parse_modrm(ord(bytes[offset])) 145 if mod == 0 and rm == 5: 146 imm = e_bits.parsebytes(bytes, offset + size, 4, sign=True) 147 size += 4 148 return(size, Amd64RipRelOper(imm, 4)) 149 150 return e_i386.i386Disasm.extended_parse_modrm(self, bytes, offset, opersize, regbase)
151 152 # NOTE: Override a bunch of the address modes to account for REX
153 - def ameth_0(self, operflags, operval, tsize, prefixes):
154 o = e_i386.i386Disasm.ameth_0(self, operflags, operval, tsize, prefixes) 155 # If it has a builtin register, we need to check for bump prefix 156 if prefixes & PREFIX_REX_B and isinstance(o, e_i386.i386RegOper): 157 o.reg += REX_BUMP 158 return o
159
160 - def ameth_g(self, bytes, offset, tsize, prefixes):
161 osize, oper = e_i386.i386Disasm.ameth_g(self, bytes, offset, tsize, prefixes) 162 if oper.tsize == 4 and oper.reg != REG_RIP: 163 oper.reg += RMETA_LOW32 164 if prefixes & PREFIX_REX_R: 165 oper.reg += REX_BUMP 166 return osize, oper
167
168 - def ameth_c(self, bytes, offset, tsize, prefixes):
169 osize, oper = e_i386.i386Disasm.ameth_c(self, bytes, offset, tsize, prefixes) 170 if prefixes & PREFIX_REX_R: 171 oper.reg += REX_BUMP 172 return osize,oper
173
174 - def ameth_d(self, bytes, offset, tsize, prefixes):
175 osize, oper = e_i386.i386Disasm.ameth_d(self, bytes, offset, tsize, prefixes) 176 if prefixes & PREFIX_REX_R: 177 oper.reg += REX_BUMP 178 return osize,oper
179
180 - def ameth_v(self, bytes, offset, tsize, prefixes):
181 osize, oper = e_i386.i386Disasm.ameth_v(self, bytes, offset, tsize, prefixes) 182 if prefixes & PREFIX_REX_R: 183 oper.reg += REX_BUMP 184 return osize,oper
185 186 # NOTE: The ones below are the only ones to which REX.X or REX.B can apply (besides ameth_0)
187 - def _dis_rex_exmodrm(self, oper, prefixes):
188 # REMEMBER: all extended mod RM reg fields come from the r/m part. If it 189 # were actually just the reg part, it'd be in one of the above 190 # addressing modes... 191 if getattr(oper, "index", None) != None: 192 if oper.tsize == 4: 193 oper.index += RMETA_LOW32 194 if prefixes & PREFIX_REX_X: 195 oper.index += REX_BUMP 196 # Adjust the size if needed 197 198 # oper.reg will be r/m or SIB base 199 if getattr(oper, "reg", None) != None: 200 # Adjust the size if needed 201 if oper.tsize == 4: 202 oper.reg += RMETA_LOW32 203 204 if prefixes & PREFIX_REX_B: 205 oper.reg += REX_BUMP
206
207 - def ameth_e(self, bytes, offset, tsize, prefixes):
208 osize, oper = e_i386.i386Disasm.ameth_e(self, bytes, offset, tsize, prefixes) 209 self._dis_rex_exmodrm(oper, prefixes) 210 return osize, oper
211
212 - def ameth_w(self, bytes, offset, tsize, prefixes):
213 osize, oper = e_i386.i386Disasm.ameth_w(self, bytes, offset, tsize, prefixes) 214 self._dis_rex_exmodrm(oper, prefixes) 215 return osize,oper
216 217 218 219 if __name__ == '__main__': 220 import sys 221 d = Amd64Disasm() 222 b = file(sys.argv[1], 'rb').read() 223 offset = 0 224 va = 0x41414141 225 while offset < len(b): 226 op = d.disasm(b, offset, va+offset) 227 print '0x%.8x %s %s' % (va+offset, b[offset:offset+len(op)].encode('hex').ljust(16), repr(op)) 228 offset += len(op) 229