diff --git a/angr_platforms/bf/lift_bf.py b/angr_platforms/bf/lift_bf.py
index 20b8cf2..149e4b8 100644
--- a/angr_platforms/bf/lift_bf.py
+++ b/angr_platforms/bf/lift_bf.py
@@ -1,7 +1,8 @@
 import bitstring
 from pyvex.lifting.util import *
 from pyvex.lifting import register
-
+from angr.engines.vex.claripy import ccall
+from angr import SimValueError
 
 # This is actually a BrainFuck lifter for pyVEX.  I'm not joking.
 # Created by edg on 1/14/2017
@@ -136,7 +137,42 @@ class BracketInstruction(Instruction):
                     self.jump_table[instr.addr] = self.addr + 1
                     return instr.addr + 1
         if len(bracket_stack) > 0:
-            raise Exception('Missing matching %s for %s at address %d' % (self.closing.name, self.name, self.addr))
+            return None
+
+    # find the matching closing tag
+    def _build_jump_table(self, state, addr):
+        jump_stack = []
+        while True:
+            try:
+                inst = chr(state.mem_concrete(addr, 1))
+            except SimValueError:
+                break
+            except KeyError:
+                break
+            if inst == '[':
+                jump_stack.append(addr)
+            elif inst == ']':
+                try:
+                    src = jump_stack.pop()
+                    dest = addr
+                    self.jump_table.update({src: dest + 1})
+                    self.jump_table.update({dest: src + 1})
+                except IndexError:
+                    raise ValueError("Extra ] at offset %d" % addr)
+            addr += 1
+        if jump_stack:
+            raise ValueError("Unmatched [s at: " + ",".join(jump_stack))
+        return True
+
+    def resolve_jump(self, state, bv_addr):
+        addr = bv_addr.args[0]
+        if not hasattr(state.scratch, 'jump_table_is_built'):
+            state.scratch.jump_table_is_built = self._build_jump_table(state, addr)
+        try:
+            return self.jump_table[addr]
+        except KeyError:
+            raise ValueError("There is no entry in the jump table at address %d" % addr)
+
 
 class Instruction_SKZ(BracketInstruction):
     bin_format = bin(ord("["))[2:].zfill(8)
@@ -161,7 +197,14 @@ class Instruction_SKZ(BracketInstruction):
         next_instr = self.constant(self.addr + 1, PTR_TYPE)
         self.jump(val == 0, next_instr)
         # And go to the next ] if *ptr == 0
-        self.jump(None, self.jump_addr)
+        if self.jump_addr:
+            self.jump(None, self.jump_addr)
+        else:
+            if not hasattr(ccall, 'resolve_jump'):
+                setattr(ccall, 'resolve_jump', self.resolve_jump)
+            jump_addr = self.ccall(PTR_TYPE,
+                    'resolve_jump', [self.constant(self.addr, PTR_TYPE)])
+            self.jump(None, jump_addr)
 
 
 class Instruction_SKNZ(BracketInstruction):
@@ -181,7 +224,10 @@ class Instruction_SKNZ(BracketInstruction):
         val = self.load(ptr, CELL_TYPE)
         next_instr = self.constant(self.addr + 1, PTR_TYPE)
         self.jump(val != 0, next_instr)
-        self.jump(None, self.jump_addr) # TODO will this break when stuff is split across blocks?
+        if self.jump_addr:
+            self.jump(None, self.jump_addr) # TODO will this break when stuff is split across blocks?
+        else:
+            raise Exception('Missing matching %s for %s at address %d' % (self.closing.name, self.name, self.addr))
 
 Instruction_SKZ.closing = Instruction_SKNZ
 Instruction_SKNZ.closing = Instruction_SKZ

