about summary refs log tree commit diff stats
path: root/miasm2/arch/x86/arch.py
diff options
context:
space:
mode:
authorCamille Mougey <commial@gmail.com>2016-01-30 16:43:30 +0100
committerCamille Mougey <commial@gmail.com>2016-01-30 16:43:30 +0100
commitdbf10438741443d59b8db500905d3d110a34c73c (patch)
tree678a6229f3ab9bd93207faedc9425d89da56275a /miasm2/arch/x86/arch.py
parent32b2b3ea15b42cbc76cb49119e76ee6e031f72ce (diff)
parent7ed8f7c5638cdca4950d05b8021233d13e339fb7 (diff)
downloadmiasm-dbf10438741443d59b8db500905d3d110a34c73c.tar.gz
miasm-dbf10438741443d59b8db500905d3d110a34c73c.zip
Merge pull request #313 from serpilliere/x86_fix
X86 fix
Diffstat (limited to 'miasm2/arch/x86/arch.py')
-rw-r--r--miasm2/arch/x86/arch.py219
1 files changed, 137 insertions, 82 deletions
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py
index a10e1038..724f6b86 100644
--- a/miasm2/arch/x86/arch.py
+++ b/miasm2/arch/x86/arch.py
@@ -272,6 +272,8 @@ deref_ptr = Group(int_or_expr + COLON +
 
 PTR = Suppress('PTR')
 
+FAR = Suppress('FAR')
+
 
 BYTE = Literal('BYTE')
 WORD = Literal('WORD')
@@ -313,6 +315,9 @@ rmarg = Group(gpregs08.parser |
 rmarg |= deref_mem
 
 
+mem_far = FAR + deref_mem
+
+
 cl_or_imm = Group(r08_ecx.parser).setParseAction(getreg)
 cl_or_imm |= int_or_expr
 
@@ -583,7 +588,13 @@ class instruction_x86(instruction):
     def arg2str(expr, pos=None):
         if isinstance(expr, ExprId) or isinstance(expr, ExprInt):
             o = str(expr)
-        elif isinstance(expr, ExprMem):
+        elif ((isinstance(expr, ExprOp) and expr.op == 'far' and
+               isinstance(expr.args[0], ExprMem)) or
+              isinstance(expr, ExprMem)):
+            if isinstance(expr, ExprOp):
+                prefix, expr = "FAR ", expr.args[0]
+            else:
+                prefix = ""
             sz = SIZE2MEMPREFIX[expr.size]
             segm = ""
             if expr.is_op_segm():
@@ -595,7 +606,7 @@ class instruction_x86(instruction):
                 s = str(expr).replace('(', '').replace(')', '')
             else:
                 s = str(expr)
-            o = sz + ' PTR %s[%s]' % (segm, s)
+            o = prefix + sz + ' PTR %s[%s]' % (segm, s)
         elif isinstance(expr, ExprOp) and expr.op == 'segm':
             o = "%s:%s" % (expr.args[0], expr.args[1])
         else:
@@ -777,9 +788,6 @@ class mn_x86(cls_mn):
                 m = a.expr
                 a.expr = ExprMem(
                     ExprOp('segm', enc2segm[self.g2.value], m.arg), m.size)
-        if self.name in ['LEA', 'LDS', 'LES', 'LFS', 'LGS', 'LSS']:
-            if not isinstance(self.args[1].expr, ExprMem):
-                return None
         return self
 
     def dup_info(self, infos):
@@ -2034,6 +2042,49 @@ class x86_rm_arg(m_arg):
         for x in self.gen_cand(v_cand, admode):
             yield x
 
+class x86_rm_mem(x86_rm_arg):
+    def fromstring(self, s, parser_result=None):
+        self.expr = None
+        start, stop = super(x86_rm_mem, self).fromstring(s, parser_result)
+        if not isinstance(self.expr, ExprMem):
+            return None, None
+        return start, stop
+
+
+class x86_rm_mem_far(x86_rm_arg):
+    parser = mem_far
+    def fromstring(self, s, parser_result=None):
+        self.expr = None
+        start, stop = super(x86_rm_mem_far, self).fromstring(s, parser_result)
+        if not isinstance(self.expr, ExprMem):
+            return None, None
+        self.expr = ExprOp('far', self.expr)
+        return start, stop
+
+    def decode(self, v):
+        ret = super(x86_rm_mem_far, self).decode(v)
+        if not ret:
+            return ret
+        if isinstance(self.expr, m2_expr.ExprMem):
+            self.expr = ExprOp('far', self.expr)
+        return True
+
+    def encode(self):
+        if not (isinstance(self.expr, m2_expr.ExprOp) and
+                self.expr.op == 'far'):
+            raise StopIteration
+
+        expr = self.expr.args[0]
+        if isinstance(expr, ExprInt):
+            raise StopIteration
+        p = self.parent
+        admode = p.v_admode()
+        mode = expr.size
+        v_cand, segm, ok = expr2modrm(expr, p, 1)
+        if segm:
+            p.g2.value = segm2enc[segm]
+        for x in self.gen_cand(v_cand, admode):
+            yield x
 
 class x86_rm_w8(x86_rm_arg):
 
@@ -3138,6 +3189,9 @@ rm_arg_m64 = bs(l=0, cls=(x86_rm_m64,), fname='rmarg')
 rm_arg_m80 = bs(l=0, cls=(x86_rm_m80,), fname='rmarg')
 rm_arg_m16 = bs(l=0, cls=(x86_rm_m16,), fname='rmarg')
 
+rm_mem = bs(l=0, cls=(x86_rm_mem,), fname='rmarg')
+rm_mem_far = bs(l=0, cls=(x86_rm_mem_far,), fname='rmarg')
+
 rm_arg_mm = bs(l=0, cls=(x86_rm_mm,), fname='rmarg')
 rm_arg_mm_m64 = bs(l=0, cls=(x86_rm_mm_m64,), fname='rmarg')
 rm_arg_mm_reg = bs(l=0, cls=(x86_rm_mm_reg,), fname='rmarg')
@@ -3150,6 +3204,74 @@ rm_arg_xmm_reg = bs(l=0, cls=(x86_rm_xmm_reg,), fname='rmarg')
 swapargs = bs_swapargs(l=1, fname="swap", mn_mod=range(1 << 1))
 
 
+class bs_op_mode(bsi):
+
+    def decode(self, v):
+        opmode = self.parent.v_opmode()
+        return opmode == self.mode
+
+
+class bs_ad_mode(bsi):
+
+    def decode(self, v):
+        admode = self.parent.v_admode()
+        return admode == self.mode
+
+
+class bs_op_mode_no64(bsi):
+
+    def encode(self):
+        if self.parent.mode == 64:
+            return False
+        return super(bs_op_mode_no64, self).encode()
+
+    def decode(self, v):
+        if self.parent.mode == 64:
+            return False
+        opmode = self.parent.v_opmode()
+        return opmode == self.mode
+
+
+class bs_op_mode64(bsi):
+    def encode(self):
+        if self.parent.mode != 64:
+            return False
+        return super(bs_op_mode64, self).encode()
+
+    def decode(self, v):
+        if self.parent.mode != 64:
+            return False
+        return True
+
+class bs_op_modeno64(bsi):
+    def encode(self):
+        if self.parent.mode == 64:
+            return False
+        return super(bs_op_modeno64, self).encode()
+
+    def decode(self, v):
+        if self.parent.mode == 64:
+            return False
+        return True
+
+
+
+bs_opmode16 = bs(l=0, cls=(bs_op_mode,), mode = 16, fname="fopmode")
+bs_opmode32 = bs(l=0, cls=(bs_op_mode,), mode = 32, fname="fopmode")
+bs_opmode64 = bs(l=0, cls=(bs_op_mode,), mode = 64, fname="fopmode")
+
+
+bs_admode16 = bs(l=0, cls=(bs_ad_mode,), mode = 16, fname="fadmode")
+bs_admode32 = bs(l=0, cls=(bs_ad_mode,), mode = 32, fname="fadmode")
+bs_admode64 = bs(l=0, cls=(bs_ad_mode,), mode = 64, fname="fadmode")
+
+bs_opmode16_no64 = bs(l=0, cls=(bs_op_mode_no64,), mode = 16, fname="fopmode")
+bs_opmode32_no64 = bs(l=0, cls=(bs_op_mode_no64,), mode = 32, fname="fopmode")
+
+bs_mode64 = bs(l=0, cls=(bs_op_mode64,))
+bs_modeno64 = bs(l=0, cls=(bs_op_modeno64,))
+
+
 cond_list = ["O", "NO", "B", "AE",
              "Z", "NZ", "BE", "A",
              "S", "NS", "PE", "NP",
@@ -3223,76 +3345,9 @@ addop("bts", [bs8(0x0f), bs8(0xba)] + rmmod(d5) + [u08])
 
 addop("call", [bs8(0xe8), rel_off])
 addop("call", [bs8(0xff), stk] + rmmod(d2))
-addop("call", [bs8(0xff), stk] + rmmod(d3, modrm=mod_mem))
-addop("call", [bs8(0x9a), moff, msegoff])
-
-
-class bs_op_mode(bsi):
-
-    def decode(self, v):
-        opmode = self.parent.v_opmode()
-        return opmode == self.mode
-
-
-class bs_ad_mode(bsi):
-
-    def decode(self, v):
-        admode = self.parent.v_admode()
-        return admode == self.mode
-
-
-class bs_op_mode_no64(bsi):
-
-    def encode(self):
-        if self.parent.mode == 64:
-            return False
-        return super(bs_op_mode_no64, self).encode()
-
-    def decode(self, v):
-        if self.parent.mode == 64:
-            return False
-        opmode = self.parent.v_opmode()
-        return opmode == self.mode
-
-
-class bs_op_mode64(bsi):
-    def encode(self):
-        if self.parent.mode != 64:
-            return False
-        return super(bs_op_mode64, self).encode()
-
-    def decode(self, v):
-        if self.parent.mode != 64:
-            return False
-        return True
-
-class bs_op_modeno64(bsi):
-    def encode(self):
-        if self.parent.mode == 64:
-            return False
-        return super(bs_op_modeno64, self).encode()
+addop("call", [bs8(0xff), stk] + rmmod(d3, rm_arg_x=rm_mem_far, modrm=mod_mem))
+addop("call", [bs8(0x9a), bs_modeno64, moff, msegoff])
 
-    def decode(self, v):
-        if self.parent.mode == 64:
-            return False
-        return True
-
-
-
-bs_opmode16 = bs(l=0, cls=(bs_op_mode,), mode = 16, fname="fopmode")
-bs_opmode32 = bs(l=0, cls=(bs_op_mode,), mode = 32, fname="fopmode")
-bs_opmode64 = bs(l=0, cls=(bs_op_mode,), mode = 64, fname="fopmode")
-
-
-bs_admode16 = bs(l=0, cls=(bs_ad_mode,), mode = 16, fname="fadmode")
-bs_admode32 = bs(l=0, cls=(bs_ad_mode,), mode = 32, fname="fadmode")
-bs_admode64 = bs(l=0, cls=(bs_ad_mode,), mode = 64, fname="fadmode")
-
-bs_opmode16_no64 = bs(l=0, cls=(bs_op_mode_no64,), mode = 16, fname="fopmode")
-bs_opmode32_no64 = bs(l=0, cls=(bs_op_mode_no64,), mode = 32, fname="fopmode")
-
-bs_mode64 = bs(l=0, cls=(bs_op_mode64,))
-bs_modeno64 = bs(l=0, cls=(bs_op_modeno64,))
 
 addop("cbw", [bs8(0x98), bs_opmode16])
 addop("cwde", [bs8(0x98), bs_opmode32])
@@ -3545,19 +3600,19 @@ addop("jmp", [bs8(0xeb), rel_off08])
 addop("jmp", [bs8(0xe9), rel_off])
 # TODO XXX replace stk force64?
 addop("jmp", [bs8(0xff), stk] + rmmod(d4))
-addop("jmpf", [bs8(0xea), moff, msegoff])
+addop("jmp", [bs8(0xea), bs_modeno64, moff, msegoff])
 
-addop("jmpf", [bs8(0xff)] + rmmod(d5))
+addop("jmp", [bs8(0xff)] + rmmod(d5, rm_arg_x=rm_mem_far, modrm=mod_mem))
 
 addop("lahf", [bs8(0x9f)])
 addop("lar", [bs8(0x0f), bs8(0x02)] + rmmod(rmreg))
 
-addop("lea", [bs8(0x8d)] + rmmod(rmreg))
-addop("les", [bs8(0xc4)] + rmmod(rmreg))
-addop("lds", [bs8(0xc5)] + rmmod(rmreg))
-addop("lss", [bs8(0x0f), bs8(0xb2)] + rmmod(rmreg))
-addop("lfs", [bs8(0x0f), bs8(0xb4)] + rmmod(rmreg))
-addop("lgs", [bs8(0x0f), bs8(0xb5)] + rmmod(rmreg))
+addop("lea", [bs8(0x8d)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem))
+addop("les", [bs8(0xc4)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem))
+addop("lds", [bs8(0xc5)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem))
+addop("lss", [bs8(0x0f), bs8(0xb2)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem))
+addop("lfs", [bs8(0x0f), bs8(0xb4)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem))
+addop("lgs", [bs8(0x0f), bs8(0xb5)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem))
 
 addop("lgdt", [bs8(0x0f), bs8(0x01)] + rmmod(d2, modrm=mod_mem))
 addop("lidt", [bs8(0x0f), bs8(0x01)] + rmmod(d3, modrm=mod_mem))