about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/arch/x86/sem.py10
-rw-r--r--miasm2/jitter/arch/JitCore_x86.c8
-rw-r--r--miasm2/jitter/codegen.py6
-rw-r--r--miasm2/jitter/csts.py1
-rw-r--r--miasm2/jitter/jitcore_python.py23
-rw-r--r--miasm2/os_dep/win_32_structs.py35
-rw-r--r--miasm2/os_dep/win_api_x86_32_seh.py149
-rw-r--r--test/arch/x86/unit/mn_seh.py106
-rw-r--r--test/test_all.py10
9 files changed, 253 insertions, 95 deletions
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index cdc98fba..565e63c5 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -2850,7 +2850,7 @@ def cmovns(ir, instr, arg1, arg2):
 def icebp(ir, instr):
     e = []
     e.append(m2_expr.ExprAff(exception_flags,
-                             m2_expr.ExprInt32(EXCEPT_PRIV_INSN)))
+                             m2_expr.ExprInt32(EXCEPT_SOFT_BP)))
     return e, []
 # XXX
 
@@ -2874,6 +2874,13 @@ def l_sysenter(ir, instr):
                              m2_expr.ExprInt32(EXCEPT_PRIV_INSN)))
     return e, []
 
+
+def l_syscall(ir, instr):
+    e = []
+    e.append(m2_expr.ExprAff(exception_flags,
+                             m2_expr.ExprInt32(EXCEPT_PRIV_INSN)))
+    return e, []
+
 # XXX
 
 
@@ -4260,6 +4267,7 @@ mnemo_func = {'mov': mov,
 
               'out': l_out,
               "sysenter": l_sysenter,
+              "syscall": l_syscall,
               "cmpxchg": cmpxchg,
               "cmpxchg8b": cmpxchg8b,
               "lds": lds,
diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c
index 0b788071..94729b90 100644
--- a/miasm2/jitter/arch/JitCore_x86.c
+++ b/miasm2/jitter/arch/JitCore_x86.c
@@ -57,6 +57,8 @@ reg_dict gpreg_dict[] = { {.name = "RAX", .offset = offsetof(vm_cpu_t, RAX)},
 			  {.name = "tsc1", .offset = offsetof(vm_cpu_t, tsc1)},
 			  {.name = "tsc2", .offset = offsetof(vm_cpu_t, tsc2)},
 
+			  {.name = "exception_flags", .offset = offsetof(vm_cpu_t, exception_flags)},
+			  {.name = "interrupt_num", .offset = offsetof(vm_cpu_t, interrupt_num)},
 };
 
 
@@ -521,6 +523,9 @@ getset_reg_u64(MM7);
 getset_reg_u32(tsc1);
 getset_reg_u32(tsc2);
 
+getset_reg_u32(exception_flags);
+getset_reg_u32(interrupt_num);
+
 
 PyObject* get_gpreg_offset_all(void)
 {
@@ -674,6 +679,9 @@ static PyGetSetDef JitCpu_getseters[] = {
     {"tsc1", (getter)JitCpu_get_tsc1, (setter)JitCpu_set_tsc1, "tsc1", NULL},
     {"tsc2", (getter)JitCpu_get_tsc2, (setter)JitCpu_set_tsc2, "tsc2", NULL},
 
+    {"exception_flags", (getter)JitCpu_get_exception_flags, (setter)JitCpu_set_exception_flags, "exception_flags", NULL},
+    {"interrupt_num", (getter)JitCpu_get_interrupt_num, (setter)JitCpu_set_interrupt_num, "interrupt_num", NULL},
+
 
     {NULL}  /* Sentinel */
 };
diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py
index 7630a2ef..c5f28b9f 100644
--- a/miasm2/jitter/codegen.py
+++ b/miasm2/jitter/codegen.py
@@ -307,14 +307,10 @@ class CGen(object):
                 return ("%s" % dst2index[label],
                         "0")
 
-        elif (isinstance(expr, m2_expr.ExprId) or
-              isinstance(expr, m2_expr.ExprMem) or
-              isinstance(expr, m2_expr.ExprSlice)):
+        else:
             dst2index[expr] = -1
             return ("-1",
                     self.id_to_c(expr))
-        else:
-            raise RuntimeError("Unsupported IRDst type %s" % expr)
 
     def gen_assignblk_dst(self, dst):
         dst2index = {}
diff --git a/miasm2/jitter/csts.py b/miasm2/jitter/csts.py
index 7af2435f..95cd34a8 100644
--- a/miasm2/jitter/csts.py
+++ b/miasm2/jitter/csts.py
@@ -4,6 +4,7 @@
 
 # VM Mngr Exceptions
 EXCEPT_DO_NOT_UPDATE_PC = 1 << 25
+EXCEPT_NUM_UPDT_EIP = (1<<11)
 
 EXCEPT_CODE_AUTOMOD = (1 << 0)
 EXCEPT_SOFT_BP = (1 << 1)
diff --git a/miasm2/jitter/jitcore_python.py b/miasm2/jitter/jitcore_python.py
index ae72b307..87259f71 100644
--- a/miasm2/jitter/jitcore_python.py
+++ b/miasm2/jitter/jitcore_python.py
@@ -1,7 +1,7 @@
 import miasm2.jitter.jitcore as jitcore
 import miasm2.expression.expression as m2_expr
 import miasm2.jitter.csts as csts
-from miasm2.expression.simplifications import expr_simp
+from miasm2.expression.simplifications import ExpressionSimplifier
 from miasm2.jitter.emulatedsymbexec import EmulatedSymbExec
 
 
@@ -17,8 +17,11 @@ class JitCore_Python(jitcore.JitCore):
         super(JitCore_Python, self).__init__(ir_arch, bs)
         self.ir_arch = ir_arch
 
-        # CPU & VM (None for now) will be set by the "jitted" Python function
-        self.symbexec = EmulatedSymbExec(None, None, self.ir_arch, {})
+        # CPU & VM (None for now) will be set later
+        expr_simp = ExpressionSimplifier()
+        expr_simp.enable_passes(ExpressionSimplifier.PASS_COMMONS)
+        self.symbexec = EmulatedSymbExec(None, None, self.ir_arch, {},
+                                         sb_expr_simp=expr_simp)
         self.symbexec.enable_emulated_simplifications()
 
     def set_cpu_vm(self, cpu, vm):
@@ -49,6 +52,7 @@ class JitCore_Python(jitcore.JitCore):
 
             # Get exec engine
             exec_engine = self.symbexec
+            expr_simp = exec_engine.expr_simp
 
             # For each irbloc inside irblocs
             while True:
@@ -87,17 +91,18 @@ class JitCore_Python(jitcore.JitCore):
                         if self.log_mn:
                             print "%08x %s" % (line.offset, line)
 
-                        # Check for memory exception
-                        if (vmmngr.get_exception() != 0):
+                        # Check for exception
+                        if (vmmngr.get_exception() != 0 or
+                            cpu.get_exception() != 0):
                             exec_engine.update_cpu_from_engine()
                             return line.offset
 
                     # Eval current instruction (in IR)
                     exec_engine.eval_ir(ir)
-
-                    # Check for memory exception which do not update PC
-                    if (vmmngr.get_exception() & csts.EXCEPT_DO_NOT_UPDATE_PC != 0):
-                        exec_engine.update_cpu_from_engine()
+                    # Check for exceptions which do not update PC
+                    exec_engine.update_cpu_from_engine()
+                    if (vmmngr.get_exception() & csts.EXCEPT_DO_NOT_UPDATE_PC != 0 or
+                        cpu.get_exception() > csts.EXCEPT_NUM_UPDT_EIP):
                         return line.offset
 
                 vmmngr.check_invalid_code_blocs()
diff --git a/miasm2/os_dep/win_32_structs.py b/miasm2/os_dep/win_32_structs.py
index 993fc79c..e76eb0a9 100644
--- a/miasm2/os_dep/win_32_structs.py
+++ b/miasm2/os_dep/win_32_structs.py
@@ -114,6 +114,39 @@ class PEB(MemStruct):
     ]
 
 
+class EXCEPTION_REGISTRATION_RECORD(MemStruct):
+    """
+    +0x00 Next    : struct _EXCEPTION_REGISTRATION_RECORD *
+    +0x04 Handler : Ptr32 Void
+    """
+
+    fields = [
+        ("Next", Ptr("<I", Self())),
+        ("Handler", Ptr("<I", Void())),
+    ]
+
+
+class EXCEPTION_RECORD(MemStruct):
+    """
+    DWORD                    ExceptionCode;
+    DWORD                    ExceptionFlags;
+    struct _EXCEPTION_RECORD *ExceptionRecord;
+    PVOID                    ExceptionAddress;
+    DWORD                    NumberParameters;
+    ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
+    """
+    EXCEPTION_MAXIMUM_PARAMETERS = 15
+
+    fields = [
+        ("ExceptionCode", Num("<I")),
+        ("ExceptionFlags", Num("<I")),
+        ("ExceptionRecord", Ptr("<I", Self())),
+        ("ExceptionAddress", Ptr("<I", Void())),
+        ("NumberParameters", Num("<I")),
+        ("ExceptionInformation", Ptr("<I", Void())),
+    ]
+
+
 class NT_TIB(MemStruct):
 
     """
@@ -128,7 +161,7 @@ class NT_TIB(MemStruct):
     """
 
     fields = [
-        ("ExceptionList", Ptr("<I", Void())),
+        ("ExceptionList", Ptr("<I", EXCEPTION_REGISTRATION_RECORD)),
         ("StackBase", Ptr("<I", Void())),
         ("StackLimit", Ptr("<I", Void())),
         ("SubSystemTib", Ptr("<I", Void())),
diff --git a/miasm2/os_dep/win_api_x86_32_seh.py b/miasm2/os_dep/win_api_x86_32_seh.py
index da8df7d7..cfd83729 100644
--- a/miasm2/os_dep/win_api_x86_32_seh.py
+++ b/miasm2/os_dep/win_api_x86_32_seh.py
@@ -29,7 +29,8 @@ from miasm2.core.utils import pck32, upck32
 import miasm2.arch.x86.regs as x86_regs
 
 from miasm2.os_dep.win_32_structs import LdrDataEntry, ListEntry, \
-    TEB, NT_TIB, PEB, PEB_LDR_DATA, ContextException
+    TEB, NT_TIB, PEB, PEB_LDR_DATA, ContextException, \
+    EXCEPTION_REGISTRATION_RECORD, EXCEPTION_RECORD
 
 # Constants Windows
 EXCEPTION_BREAKPOINT = 0x80000003
@@ -539,15 +540,14 @@ def ctxt2regs(jitter, ctxt_ptr):
     jitter.cpu.SS = ctxt.ss
 
 
-def fake_seh_handler(jitter, except_code):
+def fake_seh_handler(jitter, except_code, previous_seh=None):
     """
     Create an exception context
     @jitter: jitter instance
     @except_code: x86 exception code
+    @previous_seh: (optional) last SEH address when multiple SEH are used
     """
-
     global seh_count
-    regs = jitter.cpu.get_gpreg()
     log.warning('Exception at %x %r', jitter.cpu.EIP, seh_count)
     seh_count += 1
 
@@ -560,59 +560,49 @@ def fake_seh_handler(jitter, except_code):
 
     # Save a CONTEXT
     regs2ctxt(jitter, context_address)
+    jitter.cpu.ESP = new_ESP
 
     # Get current seh (fs:[0])
-    seh_ptr = upck32(jitter.vm.get_mem(tib_address, 4))
-
-    # Retrieve seh fields
-    old_seh, eh, safe_place = struct.unpack(
-        'III', jitter.vm.get_mem(seh_ptr, 0xc))
+    tib = NT_TIB(jitter.vm, tib_address)
+    seh = tib.ExceptionList.deref
+    if previous_seh:
+        # Recursive SEH
+        while seh.get_addr() != previous_seh:
+            seh = seh.Next.deref
+        seh = seh.Next.deref
 
-    log.info('seh_ptr %x { old_seh %x eh %x safe_place %x} ctx_addr %x',
-             seh_ptr, old_seh, eh, safe_place, context_address)
+    log.info('seh_ptr %x { old_seh %r eh %r} ctx_addr %x',
+             seh.get_addr(), seh.Next, seh.Handler, context_address)
 
-    jitter.cpu.ESP = new_ESP
     # Write exception_record
-
-    """
-    #http://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx
-
-    typedef struct _EXCEPTION_RECORD {
-      DWORD                    ExceptionCode;
-      DWORD                    ExceptionFlags;
-      struct _EXCEPTION_RECORD *ExceptionRecord;
-      PVOID                    ExceptionAddress;
-      DWORD                    NumberParameters;
-      ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
-    } EXCEPTION_RECORD, *PEXCEPTION_RECORD;
-    """
-
-    jitter.vm.set_mem(exception_record_address,
-                      pck32(except_code) + pck32(0) + pck32(0) +
-                      pck32(jitter.cpu.EIP) + pck32(0))
+    except_record = EXCEPTION_RECORD(jitter.vm, exception_record_address)
+    except_record.memset("\x00")
+    except_record.ExceptionCode = except_code
+    except_record.ExceptionAddress = jitter.cpu.EIP
 
     # Prepare the stack
     jitter.push_uint32_t(context_address)               # Context
-    jitter.push_uint32_t(seh_ptr)                       # SEH
-    jitter.push_uint32_t(exception_record_address)      # ExceptRecords
+    jitter.push_uint32_t(seh.get_addr())                # SEH
+    jitter.push_uint32_t(except_record.get_addr())      # ExceptRecords
     jitter.push_uint32_t(return_from_exception)         # Ret address
 
     # Set fake new current seh for exception
     log.info("Fake seh ad %x", fake_seh_address)
-    jitter.vm.set_mem(fake_seh_address, pck32(seh_ptr) + pck32(
-        0xaaaaaaaa) + pck32(0xaaaaaabb) + pck32(0xaaaaaacc))
-    jitter.vm.set_mem(tib_address, pck32(fake_seh_address))
-
+    fake_seh = EXCEPTION_REGISTRATION_RECORD(jitter.vm, fake_seh_address)
+    fake_seh.Next.val = tib.ExceptionList.val
+    fake_seh.Handler = 0xaaaaaaaa
+    tib.ExceptionList.val = fake_seh.get_addr()
     dump_seh(jitter)
 
-    log.info('Jumping at %x', eh)
+    # Remove exceptions
     jitter.vm.set_exception(0)
     jitter.cpu.set_exception(0)
 
     # XXX set ebx to nul?
     jitter.cpu.EBX = 0
 
-    return eh
+    log.info('Jumping at %r', seh.Handler)
+    return seh.Handler.val
 
 
 def dump_seh(jitter):
@@ -620,24 +610,18 @@ def dump_seh(jitter):
     Walk and dump the SEH entries
     @jitter: jitter instance
     """
-
     log.info('Dump_seh. Tib_address: %x', tib_address)
-    cur_seh_ptr = upck32(jitter.vm.get_mem(tib_address, 4))
-    indent = 1
+    cur_seh_ptr = NT_TIB(jitter.vm, tib_address).ExceptionList
     loop = 0
-    while True:
+    while cur_seh_ptr and jitter.vm.is_mapped(cur_seh_ptr.val,
+                                              len(cur_seh_ptr)):
         if loop > MAX_SEH:
             log.warn("Too many seh, quit")
             return
-        if not jitter.vm.is_mapped(cur_seh_ptr, 8):
-            break
-        prev_seh, eh = struct.unpack('II', jitter.vm.get_mem(cur_seh_ptr, 8))
-        log.info('\t' * indent + 'seh_ptr: %x { prev_seh: %x eh %x }',
-                 cur_seh_ptr, prev_seh, eh)
-        if prev_seh == 0:
-            break
-        cur_seh_ptr = prev_seh
-        indent += 1
+        err = cur_seh_ptr.deref
+        log.info('\t' * (loop + 1) + 'seh_ptr: %x { prev_seh: %r eh %r }',
+                 err.get_addr(), err.Next, err.Handler)
+        cur_seh_ptr = err.Next
         loop += 1
 
 
@@ -647,11 +631,8 @@ def set_win_fs_0(jitter, fs=4):
     @jitter: jitter instance
     @fs: segment selector value
     """
-
-    regs = jitter.cpu.get_gpreg()
-    regs['FS'] = 0x4
-    jitter.cpu.set_gpreg(regs)
-    jitter.cpu.set_segm_base(regs['FS'], FS_0_AD)
+    jitter.cpu.FS = fs
+    jitter.cpu.set_segm_base(fs, FS_0_AD)
     segm_to_do = set([x86_regs.FS])
     return segm_to_do
 
@@ -660,34 +641,48 @@ def return_from_seh(jitter):
     """Handle the return from an exception handler
     @jitter: jitter instance"""
 
-    # Get current context
+    # Get object addresses
+    seh_address = upck32(jitter.vm.get_mem(jitter.cpu.ESP + 0x4, 4))
     context_address = upck32(jitter.vm.get_mem(jitter.cpu.ESP + 0x8, 4))
-    log.info('Context address: %x', context_address)
-    jitter.cpu.ESP = upck32(jitter.vm.get_mem(context_address + 0xc4, 4))
-    log.info('New esp: %x', jitter.cpu.ESP)
-
-    # Rebuild SEH
-    old_seh = upck32(jitter.vm.get_mem(tib_address, 4))
-    new_seh = upck32(jitter.vm.get_mem(old_seh, 4))
-    log.info('Old seh: %x New seh: %x', old_seh, new_seh)
-    jitter.vm.set_mem(tib_address, pck32(new_seh))
 
+    # Get registers changes
+    log.info('Context address: %x', context_address)
+    status = jitter.cpu.EAX
+    ctxt2regs(jitter, context_address)
+
+    # Rebuild SEH (remove fake SEH)
+    tib = NT_TIB(jitter.vm, tib_address)
+    seh = tib.ExceptionList.deref
+    log.info('Old seh: %x New seh: %x', seh.get_addr(), seh.Next.val)
+    tib.ExceptionList.val = seh.Next.val
     dump_seh(jitter)
 
-    if jitter.cpu.EAX == 0x0:
+    # Handle returned values
+    if status == 0x0:
         # ExceptionContinueExecution
-        ctxt_ptr = context_address
-        log.info('Seh continues Context: %x', ctxt_ptr)
-
-        # Get registers changes
-        # ctxt_str = jitter.vm.get_mem(ctxt_ptr, 0x2cc)
-        ctxt2regs(jitter, ctxt_ptr)
+        log.info('SEH continue')
         jitter.pc = jitter.cpu.EIP
         log.info('Context::Eip: %x', jitter.pc)
 
-    elif jitter.cpu.EAX == -1:
-        raise NotImplementedError("-> seh try to go to the next handler")
-
-    elif jitter.cpu.EAX == 1:
+    elif status == 1:
         # ExceptionContinueSearch
-        raise NotImplementedError("-> seh, gameover")
+        log.info("Delegate to the next SEH handler")
+        # exception_base_address: context_address - 0xfc
+        # -> exception_record_address: exception_base_address + 0xe8
+        exception_record = EXCEPTION_RECORD(jitter.vm,
+                                            context_address - 0xfc + 0xe8)
+
+        pc = fake_seh_handler(jitter, exception_record.ExceptionCode,
+                              seh_address)
+        jitter.pc = pc
+
+    else:
+        # https://msdn.microsoft.com/en-us/library/aa260344%28v=vs.60%29.aspx
+        # But the type _EXCEPTION_DISPOSITION may take 2 others values:
+        #  - ExceptionNestedException = 2
+        #  - ExceptionCollidedUnwind = 3
+        raise ValueError("Valid values are ExceptionContinueExecution and "
+                         "ExceptionContinueSearch")
+
+    # Jitter's breakpoint compliant
+    return True
diff --git a/test/arch/x86/unit/mn_seh.py b/test/arch/x86/unit/mn_seh.py
new file mode 100644
index 00000000..cc8b5cc2
--- /dev/null
+++ b/test/arch/x86/unit/mn_seh.py
@@ -0,0 +1,106 @@
+#! /usr/bin/env python
+import sys
+
+from miasm2.os_dep.win_api_x86_32_seh import fake_seh_handler, build_teb, \
+    set_win_fs_0, return_from_exception, EXCEPTION_PRIV_INSTRUCTION, \
+    return_from_seh, FS_0_AD, DEFAULT_SEH
+from miasm2.os_dep.win_32_structs import ContextException
+
+from asm_test import Asm_Test_32
+
+from pdb import pm
+
+class Test_SEH(Asm_Test_32):
+    """SEH Handling"""
+
+    @staticmethod
+    def deal_exception_priv(jitter):
+        print 'Exception Priv', hex(jitter.cpu.ESP)
+        pc = fake_seh_handler(jitter, EXCEPTION_PRIV_INSTRUCTION)
+        jitter.pc = pc
+        jitter.cpu.EIP = pc
+        return True
+
+    def init_machine(self):
+        super(Test_SEH, self).init_machine()
+        build_teb(self.myjit, FS_0_AD)
+        set_win_fs_0(self.myjit)
+        self.myjit.add_exception_handler((1 << 17),
+                                         Test_SEH.deal_exception_priv)
+        self.myjit.add_breakpoint(return_from_exception, return_from_seh)
+
+
+class Test_SEH_simple(Test_SEH):
+    TXT = '''
+    main:
+       XOR EAX, EAX
+       XOR EDX, EDX
+
+       PUSH handler
+       PUSH DWORD PTR FS:[EDX]
+       MOV DWORD PTR FS:[EDX], ESP
+
+       STI
+
+       MOV EBX, DWORD PTR [ESP]
+       MOV DWORD PTR FS:[EDX], EBX
+       ADD ESP, 0x8
+
+       RET
+
+    handler:
+       MOV ECX, DWORD PTR [ESP+0xC]
+       INC DWORD PTR [ECX+0x%08x]
+       MOV DWORD PTR [ECX+0x%08x], 0xcafebabe
+       XOR EAX, EAX
+       RET
+    ''' % (ContextException.get_offset("eip"),
+           ContextException.get_offset("eax"))
+
+    def check(self):
+        assert(self.myjit.cpu.EAX == 0xcafebabe)
+        assert(self.myjit.cpu.EBX == DEFAULT_SEH)
+
+
+class Test_SEH_double(Test_SEH_simple):
+    TXT = '''
+    main:
+       XOR EAX, EAX
+       XOR EDX, EDX
+
+       PUSH handler1
+       PUSH DWORD PTR FS:[EDX]
+       MOV DWORD PTR FS:[EDX], ESP
+
+       PUSH handler2
+       PUSH DWORD PTR FS:[EDX]
+       MOV DWORD PTR FS:[EDX], ESP
+
+       STI
+
+       MOV EBX, DWORD PTR [ESP]
+       MOV DWORD PTR FS:[EDX], EBX
+       ADD ESP, 0x8
+
+       MOV EBX, DWORD PTR [ESP]
+       MOV DWORD PTR FS:[EDX], EBX
+       ADD ESP, 0x8
+
+       RET
+
+    handler1:
+       MOV EAX, 0x1
+       RET
+
+    handler2:
+       MOV ECX, DWORD PTR [ESP+0xC]
+       INC DWORD PTR [ECX+0x%08x]
+       MOV DWORD PTR [ECX+0x%08x], 0xcafebabe
+       XOR EAX, EAX
+       RET
+    ''' % (ContextException.get_offset("eip"),
+           ContextException.get_offset("eax"))
+
+
+if __name__ == "__main__":
+    [test(*sys.argv[1:])() for test in [Test_SEH_simple, Test_SEH_double]]
diff --git a/test/test_all.py b/test/test_all.py
index c3e3c1fb..7b878c89 100644
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -48,12 +48,15 @@ testset += RegressionTest(["x86/arch.py"], base_dir="arch",
 class ArchUnitTest(RegressionTest):
     """Test against arch unit regression tests"""
 
-    jitter_engines = ["tcc", "llvm", "gcc"]
+    jitter_engines = ["tcc", "llvm", "gcc", "python"]
 
     def __init__(self, script, jitter ,*args, **kwargs):
         super(ArchUnitTest, self).__init__([script, jitter], *args, **kwargs)
 
-
+# script -> blacklisted jitter
+blacklist = {
+    "x86/unit/mn_float.py": ["python"],
+}
 for script in ["x86/sem.py",
                "x86/unit/mn_strings.py",
                "x86/unit/mn_float.py",
@@ -71,6 +74,7 @@ for script in ["x86/sem.py",
                "x86/unit/mn_pextr.py",
                "x86/unit/mn_pmovmskb.py",
                "x86/unit/mn_pushpop.py",
+               "x86/unit/mn_seh.py",
                "arm/arch.py",
                "arm/sem.py",
                "aarch64/unit/mn_ubfm.py",
@@ -82,6 +86,8 @@ for script in ["x86/sem.py",
                "mips32/unit/mn_bcc.py",
                ]:
     for jitter in ArchUnitTest.jitter_engines:
+        if jitter in blacklist.get(script, []):
+            continue
         tags = [TAGS[jitter]] if jitter in TAGS else []
         testset += ArchUnitTest(script, jitter, base_dir="arch", tags=tags)