about summary refs log tree commit diff stats
path: root/miasm2/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/analysis')
-rw-r--r--miasm2/analysis/binary.py34
-rw-r--r--miasm2/analysis/cst_propag.py6
-rw-r--r--miasm2/analysis/data_analysis.py39
-rw-r--r--miasm2/analysis/data_flow.py100
-rw-r--r--miasm2/analysis/debugging.py175
-rw-r--r--miasm2/analysis/depgraph.py43
-rw-r--r--miasm2/analysis/disasm_cb.py24
-rw-r--r--miasm2/analysis/dse.py59
-rw-r--r--miasm2/analysis/expression_range.py11
-rw-r--r--miasm2/analysis/gdbserver.py336
-rw-r--r--miasm2/analysis/modularintervals.py11
-rw-r--r--miasm2/analysis/outofssa.py28
-rw-r--r--miasm2/analysis/sandbox.py148
-rw-r--r--miasm2/analysis/simplifier.py4
-rw-r--r--miasm2/analysis/ssa.py41
15 files changed, 602 insertions, 457 deletions
diff --git a/miasm2/analysis/binary.py b/miasm2/analysis/binary.py
index 93bd74b2..ee733d79 100644
--- a/miasm2/analysis/binary.py
+++ b/miasm2/analysis/binary.py
@@ -46,7 +46,7 @@ class Container(object):
                 return container_type(data, *args, **kwargs)
             except ContainerSignatureException:
                 continue
-            except ContainerParsingException, error:
+            except ContainerParsingException as error:
                 log.error(error)
 
         # Fallback mode
@@ -134,7 +134,7 @@ class ContainerPE(Container):
         from elfesteem import pe_init
 
         # Parse signature
-        if not data.startswith('MZ'):
+        if not data.startswith(b'MZ'):
             raise ContainerSignatureException()
 
         # Build executable instance
@@ -143,7 +143,7 @@ class ContainerPE(Container):
                 self._executable = vm_load_pe(vm, data)
             else:
                 self._executable = pe_init.PE(data)
-        except Exception, error:
+        except Exception as error:
             raise ContainerParsingException('Cannot read PE: %s' % error)
 
         # Check instance validity
@@ -159,7 +159,7 @@ class ContainerPE(Container):
             self._bin_stream = bin_stream_pe(self._executable)
             ep_detected = self._executable.Opthdr.AddressOfEntryPoint
             self._entry_point = self._executable.rva2virt(ep_detected)
-        except Exception, error:
+        except Exception as error:
             raise ContainerParsingException('Cannot read PE: %s' % error)
 
 
@@ -168,7 +168,7 @@ class ContainerELF(Container):
 
     def parse(self, data, vm=None, addr=0, apply_reloc=False, **kwargs):
         """Load an ELF from @data
-        @data: str containing the ELF bytes
+        @data: bytes containing the ELF bytes
         @vm (optional): VmMngr instance. If set, load the ELF in virtual memory
         @addr (optional): base address the ELF in virtual memory
         @apply_reloc (optional): if set, apply relocation during ELF loading
@@ -181,18 +181,22 @@ class ContainerELF(Container):
         from elfesteem import elf_init
 
         # Parse signature
-        if not data.startswith('\x7fELF'):
+        if not data.startswith(b'\x7fELF'):
             raise ContainerSignatureException()
 
         # Build executable instance
         try:
             if vm is not None:
-                self._executable = vm_load_elf(vm, data, loc_db=self.loc_db,
-                                               base_addr=addr,
-                                               apply_reloc=apply_reloc)
+                self._executable = vm_load_elf(
+                    vm,
+                    data,
+                    loc_db=self.loc_db,
+                    base_addr=addr,
+                    apply_reloc=apply_reloc
+                )
             else:
                 self._executable = elf_init.ELF(data)
-        except Exception, error:
+        except Exception as error:
             raise ContainerParsingException('Cannot read ELF: %s' % error)
 
         # Guess the architecture
@@ -202,7 +206,7 @@ class ContainerELF(Container):
         try:
             self._bin_stream = bin_stream_elf(self._executable)
             self._entry_point = self._executable.Ehdr.entry + addr
-        except Exception, error:
+        except Exception as error:
             raise ContainerParsingException('Cannot read ELF: %s' % error)
 
         if vm is None:
@@ -217,9 +221,11 @@ class ContainerUnknown(Container):
     def parse(self, data, vm=None, addr=0, **kwargs):
         self._bin_stream = bin_stream_str(data, base_address=addr)
         if vm is not None:
-            vm.add_memory_page(addr,
-                               PAGE_READ,
-                               data)
+            vm.add_memory_page(
+                addr,
+                PAGE_READ,
+                data
+            )
         self._executable = None
         self._entry_point = 0
 
diff --git a/miasm2/analysis/cst_propag.py b/miasm2/analysis/cst_propag.py
index 9a5e3d54..25d66318 100644
--- a/miasm2/analysis/cst_propag.py
+++ b/miasm2/analysis/cst_propag.py
@@ -1,5 +1,7 @@
 import logging
 
+from future.utils import viewitems
+
 from miasm2.ir.symbexec import SymbolicExecutionEngine
 from miasm2.expression.expression import ExprMem
 from miasm2.expression.expression_helper import possible_values
@@ -95,7 +97,7 @@ class SymbExecStateFix(SymbolicExecutionEngine):
         for index, assignblk in enumerate(irb):
             new_assignblk = {}
             links = {}
-            for dst, src in assignblk.iteritems():
+            for dst, src in viewitems(assignblk):
                 src = self.propag_expr_cst(src)
                 if dst.is_mem():
                     ptr = dst.ptr
@@ -175,7 +177,7 @@ def propagate_cst_expr(ir_arch, ircfg, addr, init_infos):
     """
     states = compute_cst_propagation_states(ir_arch, ircfg, addr, init_infos)
     cst_propag_link = {}
-    for lbl, state in states.iteritems():
+    for lbl, state in viewitems(states):
         if lbl not in ircfg.blocks:
             continue
         symbexec = SymbExecStateFix(ir_arch, ircfg, state, cst_propag_link)
diff --git a/miasm2/analysis/data_analysis.py b/miasm2/analysis/data_analysis.py
index 30346e63..bd073fcb 100644
--- a/miasm2/analysis/data_analysis.py
+++ b/miasm2/analysis/data_analysis.py
@@ -1,5 +1,12 @@
+from __future__ import print_function
+
+from future.utils import viewitems
+
+from builtins import object
+from functools import cmp_to_key
 from miasm2.expression.expression \
-    import get_expr_mem, get_list_rw, ExprId, ExprInt
+    import get_expr_mem, get_list_rw, ExprId, ExprInt, \
+    compare_exprs
 from miasm2.ir.symbexec import SymbolicExecutionEngine
 
 
@@ -19,7 +26,7 @@ def intra_block_flow_raw(ir_arch, ircfg, flow_graph, irb, in_nodes, out_nodes):
 
         # gen mem arg to mem node links
         all_mems = set()
-        for node_w, nodes_r in dict_rw.iteritems():
+        for node_w, nodes_r in viewitems(dict_rw):
             for n in nodes_r.union([node_w]):
                 all_mems.update(get_expr_mem(n))
             if not all_mems:
@@ -40,7 +47,7 @@ def intra_block_flow_raw(ir_arch, ircfg, flow_graph, irb, in_nodes, out_nodes):
                     flow_graph.add_uniq_edge(node_n_r, node_n_w)
 
         # gen data flow links
-        for node_w, nodes_r in dict_rw.iteritems():
+        for node_w, nodes_r in viewitems(dict_rw):
             for n_r in nodes_r:
                 if n_r in current_nodes:
                     node_n_r = current_nodes[n_r]
@@ -65,11 +72,11 @@ def inter_block_flow_link(ir_arch, ircfg, flow_graph, irb_in_nodes, irb_out_node
 
     # link current nodes to bloc in_nodes
     if not lbl in ircfg.blocks:
-        print "cannot find bloc!!", lbl
+        print("cannot find bloc!!", lbl)
         return set()
     irb = ircfg.blocks[lbl]
     to_del = set()
-    for n_r, node_n_r in irb_in_nodes[irb.loc_key].items():
+    for n_r, node_n_r in viewitems(irb_in_nodes[irb.loc_key]):
         if not n_r in current_nodes:
             continue
         flow_graph.add_uniq_edge(current_nodes[n_r], node_n_r)
@@ -78,7 +85,7 @@ def inter_block_flow_link(ir_arch, ircfg, flow_graph, irb_in_nodes, irb_out_node
     # if link exec to data, all nodes depends on exec nodes
     if link_exec_to_data:
         for n_x_r in exec_nodes:
-            for n_r, node_n_r in irb_in_nodes[irb.loc_key].items():
+            for n_r, node_n_r in viewitems(irb_in_nodes[irb.loc_key]):
                 if not n_x_r in current_nodes:
                     continue
                 if isinstance(n_r, ExprInt):
@@ -86,15 +93,15 @@ def inter_block_flow_link(ir_arch, ircfg, flow_graph, irb_in_nodes, irb_out_node
                 flow_graph.add_uniq_edge(current_nodes[n_x_r], node_n_r)
 
     # update current nodes using bloc out_nodes
-    for n_w, node_n_w in irb_out_nodes[irb.loc_key].items():
+    for n_w, node_n_w in viewitems(irb_out_nodes[irb.loc_key]):
         current_nodes[n_w] = node_n_w
 
     # get nodes involved in exec flow
-    x_nodes = tuple(sorted(list(irb.dst.get_r())))
+    x_nodes = tuple(sorted(irb.dst.get_r(), key=cmp_to_key(compare_exprs)))
 
     todo = set()
     for lbl_dst in ircfg.successors(irb.loc_key):
-        todo.add((lbl_dst, tuple(current_nodes.items()), x_nodes))
+        todo.add((lbl_dst, tuple(viewitems(current_nodes)), x_nodes))
 
     return todo
 
@@ -109,7 +116,7 @@ def create_implicit_flow(ir_arch, flow_graph, irb_in_nodes, irb_out_ndes):
         irb = ir_arch.blocks[lbl]
         for lbl_son in ir_arch.graph.successors(irb.loc_key):
             if not lbl_son in ir_arch.blocks:
-                print "cannot find bloc!!", lbl
+                print("cannot find bloc!!", lbl)
                 continue
             irb_son = ir_arch.blocks[lbl_son]
             for n_r in irb_in_nodes[irb_son.loc_key]:
@@ -144,7 +151,7 @@ def inter_block_flow(ir_arch, ircfg, flow_graph, irb_0, irb_in_nodes, irb_out_no
         todo.update(out)
 
 
-class symb_exec_func:
+class symb_exec_func(object):
 
     """
     This algorithm will do symbolic execution on a function, trying to propagate
@@ -164,15 +171,13 @@ class symb_exec_func:
         self.ir_arch = ir_arch
 
     def add_state(self, parent, ad, state):
-        variables = dict(state.symbols.items())
+        variables = dict(state.symbols)
 
         # get bloc dead, and remove from state
         b = self.ir_arch.get_block(ad)
         if b is None:
             raise ValueError("unknown bloc! %s" % ad)
-        variables = variables.items()
-
-        s = parent, ad, tuple(sorted(variables))
+        s = parent, ad, tuple(sorted(viewitems(variables)))
         self.todo.add(s)
 
     def get_next_state(self):
@@ -183,10 +188,10 @@ class symb_exec_func:
         if len(self.todo) == 0:
             return None
         if self.total_done > 600:
-            print "symbexec watchdog!"
+            print("symbexec watchdog!")
             return None
         self.total_done += 1
-        print 'CPT', self.total_done
+        print('CPT', self.total_done)
         while self.todo:
             state = self.get_next_state()
             parent, ad, s = state
diff --git a/miasm2/analysis/data_flow.py b/miasm2/analysis/data_flow.py
index 2201a088..3874b21b 100644
--- a/miasm2/analysis/data_flow.py
+++ b/miasm2/analysis/data_flow.py
@@ -1,6 +1,8 @@
 """Data flow analysis based on miasm intermediate representation"""
-
+from builtins import range
 from collections import namedtuple
+from future.utils import viewitems, viewvalues
+from miasm2.core.utils import encode_hex
 from miasm2.core.graph import DiGraph
 from miasm2.ir.ir import AssignBlock, IRBlock
 from miasm2.expression.expression import ExprLoc, ExprMem, ExprId, ExprInt,\
@@ -56,7 +58,7 @@ class ReachingDefinitions(dict):
         modified = True
         while modified:
             modified = False
-            for block in self.ircfg.blocks.itervalues():
+            for block in viewvalues(self.ircfg.blocks):
                 modified |= self.process_block(block)
 
     def process_block(self, block):
@@ -67,7 +69,7 @@ class ReachingDefinitions(dict):
         predecessor_state = {}
         for pred_lbl in self.ircfg.predecessors(block.loc_key):
             pred = self.ircfg.blocks[pred_lbl]
-            for lval, definitions in self.get_definitions(pred_lbl, len(pred)).iteritems():
+            for lval, definitions in viewitems(self.get_definitions(pred_lbl, len(pred))):
                 predecessor_state.setdefault(lval, set()).update(definitions)
 
         modified = self.get((block.loc_key, 0)) != predecessor_state
@@ -75,7 +77,7 @@ class ReachingDefinitions(dict):
             return False
         self[(block.loc_key, 0)] = predecessor_state
 
-        for index in xrange(len(block)):
+        for index in range(len(block)):
             modified |= self.process_assignblock(block, index)
         return modified
 
@@ -151,7 +153,7 @@ class DiGraphDefUse(DiGraph):
 
     def _compute_def_use(self, reaching_defs,
                          deref_mem=False):
-        for block in self._blocks.itervalues():
+        for block in viewvalues(self._blocks):
             self._compute_def_use_block(block,
                                         reaching_defs,
                                         deref_mem=deref_mem)
@@ -159,7 +161,7 @@ class DiGraphDefUse(DiGraph):
     def _compute_def_use_block(self, block, reaching_defs, deref_mem=False):
         for index, assignblk in enumerate(block):
             assignblk_reaching_defs = reaching_defs.get_definitions(block.loc_key, index)
-            for lval, expr in assignblk.iteritems():
+            for lval, expr in viewitems(assignblk):
                 self.add_node(AssignblkNode(block.loc_key, index, lval))
 
                 read_vars = expr.get_r(mem_read=deref_mem)
@@ -212,7 +214,7 @@ def dead_simp_useful_assignblks(irarch, defuse, reaching_defs):
     ircfg = reaching_defs.ircfg
     useful = set()
 
-    for block_lbl, block in ircfg.blocks.iteritems():
+    for block_lbl, block in viewitems(ircfg.blocks):
         successors = ircfg.successors(block_lbl)
         for successor in successors:
             if successor not in ircfg.blocks:
@@ -225,14 +227,14 @@ def dead_simp_useful_assignblks(irarch, defuse, reaching_defs):
         if keep_all_definitions or (len(successors) == 0):
             valid_definitions = reaching_defs.get_definitions(block_lbl,
                                                               len(block))
-            for lval, definitions in valid_definitions.iteritems():
+            for lval, definitions in viewitems(valid_definitions):
                 if lval in irarch.get_out_regs(block) or keep_all_definitions:
                     for definition in definitions:
                         useful.add(AssignblkNode(definition[0], definition[1], lval))
 
         # Force keeping of specific cases
         for index, assignblk in enumerate(block):
-            for lval, rval in assignblk.iteritems():
+            for lval, rval in viewitems(assignblk):
                 if (lval.is_mem() or
                     irarch.IRDst == lval or
                     lval.is_id("exception_flags") or
@@ -262,7 +264,7 @@ def dead_simp(irarch, ircfg):
     reaching_defs = ReachingDefinitions(ircfg)
     defuse = DiGraphDefUse(reaching_defs, deref_mem=True)
     useful = set(dead_simp_useful_assignblks(irarch, defuse, reaching_defs))
-    for block in ircfg.blocks.itervalues():
+    for block in list(viewvalues(ircfg.blocks)):
         irs = []
         for idx, assignblk in enumerate(block):
             new_assignblk = dict(assignblk)
@@ -311,7 +313,7 @@ def _do_merge_blocks(ircfg, loc_key, son_loc_key):
             assignblks.append(assignblk)
             continue
         affs = {}
-        for dst, src in assignblk.iteritems():
+        for dst, src in viewitems(assignblk):
             if dst != ircfg.IRDst:
                 affs[dst] = src
         if affs:
@@ -348,7 +350,7 @@ def _test_jmp_only(ircfg, loc_key, heads):
     irblock = ircfg.blocks[loc_key]
     if len(irblock.assignblks) != 1:
         return None
-    items = dict(irblock.assignblks[0]).items()
+    items = list(viewitems(dict(irblock.assignblks[0])))
     if len(items) != 1:
         return None
     if len(ircfg.successors(loc_key)) != 1:
@@ -528,7 +530,7 @@ def remove_empty_assignblks(ircfg):
     @ircfg: IRCFG instance
     """
     modified = False
-    for loc_key, block in ircfg.blocks.iteritems():
+    for loc_key, block in list(viewitems(ircfg.blocks)):
         irs = []
         block_modified = False
         for assignblk in block:
@@ -591,13 +593,13 @@ class SSADefUse(DiGraph):
             if block is None:
                 continue
             for index, assignblk in enumerate(block):
-                for dst, src in assignblk.iteritems():
+                for dst, src in viewitems(assignblk):
                     node = AssignblkNode(lbl, index, dst)
                     graph.add_var_def(node, src)
                     graph.add_def_node(def_nodes, node, src)
                     graph.add_use_node(use_nodes, node, src)
 
-        for dst, node in def_nodes.iteritems():
+        for dst, node in viewitems(def_nodes):
             graph.add_node(node)
             if dst not in use_nodes:
                 continue
@@ -650,7 +652,7 @@ class PropagateThroughExprId(object):
         @assignblks: list of AssignBlock to check
         """
         for assignblk in assignblks:
-            for dst, src in assignblk.iteritems():
+            for dst, src in viewitems(assignblk):
                 if src.is_function_call():
                     return True
                 if dst.is_mem():
@@ -723,7 +725,7 @@ class PropagateThroughExprId(object):
         def_dct = {}
         for node in ircfg.nodes():
             for index, assignblk in enumerate(ircfg.blocks[node]):
-                for dst, src in assignblk.iteritems():
+                for dst, src in viewitems(assignblk):
                     if not dst.is_id():
                         continue
                     if dst in ssa.immutable_ids:
@@ -786,7 +788,7 @@ class PropagateThroughExprId(object):
         """
         node_to_reg, to_replace, defuse = self.get_candidates(ssa, head, max_expr_depth)
         modified = False
-        for node, reg in node_to_reg.iteritems():
+        for node, reg in viewitems(node_to_reg):
             for successor in defuse.successors(node):
                 if not self.propagation_allowed(ssa, to_replace, node, successor):
                     continue
@@ -800,7 +802,7 @@ class PropagateThroughExprId(object):
                 assignblks = list(block)
                 assignblk = block[node_b.index]
                 out = {}
-                for dst, src in assignblk.iteritems():
+                for dst, src in viewitems(assignblk):
                     if src.is_op('Phi'):
                         out[dst] = src
                         continue
@@ -874,16 +876,16 @@ class PropagateThroughExprMem(object):
         ircfg = ssa.graph
         todo = set()
         modified = False
-        for block in ircfg.blocks.itervalues():
+        for block in viewvalues(ircfg.blocks):
             for i, assignblk in enumerate(block):
-                for dst, src in assignblk.iteritems():
+                for dst, src in viewitems(assignblk):
                     if not dst.is_mem():
                         continue
                     if expr_has_mem(src):
                         continue
                     todo.add((block.loc_key, i + 1, dst, src))
                     ptr = dst.ptr
-                    for size in xrange(8, dst.size, 8):
+                    for size in range(8, dst.size, 8):
                         todo.add((block.loc_key, i + 1, ExprMem(ptr, size), src[:size]))
 
         while todo:
@@ -891,13 +893,13 @@ class PropagateThroughExprMem(object):
             block = ircfg.blocks[loc_key]
             assignblks = list(block)
             block_modified = False
-            for i in xrange(index, len(block)):
+            for i in range(index, len(block)):
                 assignblk = block[i]
                 write_mem = False
                 assignblk_modified = False
                 out = dict(assignblk)
                 out_new = {}
-                for dst, src in out.iteritems():
+                for dst, src in viewitems(out):
                     if dst.is_mem():
                         write_mem = True
                         ptr = dst.ptr.replace_expr({mem_dst:mem_src})
@@ -941,7 +943,7 @@ def stack_to_reg(expr):
             diff = int(ptr.args[1])
             assert diff % 4 == 0
             diff = (0 - diff) & 0xFFFFFFFF
-            return ExprId("STACK.%d" % (diff / 4), expr.size)
+            return ExprId("STACK.%d" % (diff // 4), expr.size)
     return False
 
 
@@ -997,12 +999,12 @@ def retrieve_stack_accesses(ir_arch_a, ircfg):
     @ircfg: IRCFG instance
     """
     stack_vars = set()
-    for block in ircfg.blocks.itervalues():
+    for block in viewvalues(ircfg.blocks):
         for assignblk in block:
-            for dst, src in assignblk.iteritems():
+            for dst, src in viewitems(assignblk):
                 stack_vars.update(get_stack_accesses(ir_arch_a, dst))
                 stack_vars.update(get_stack_accesses(ir_arch_a, src))
-    stack_vars = filter(lambda expr: check_expr_below_stack(ir_arch_a, expr), stack_vars)
+    stack_vars = [expr for expr in stack_vars if check_expr_below_stack(ir_arch_a, expr)]
 
     base_to_var = {}
     for var in stack_vars:
@@ -1010,7 +1012,7 @@ def retrieve_stack_accesses(ir_arch_a, ircfg):
 
 
     base_to_interval = {}
-    for addr, vars in base_to_var.iteritems():
+    for addr, vars in viewitems(base_to_var):
         var_interval = interval()
         for var in vars:
             offset = expr_simp(addr - ir_arch_a.sp)
@@ -1019,7 +1021,7 @@ def retrieve_stack_accesses(ir_arch_a, ircfg):
                 continue
 
             start = int(offset)
-            stop = int(expr_simp(offset + ExprInt(var.size / 8, offset.size)))
+            stop = int(expr_simp(offset + ExprInt(var.size // 8, offset.size)))
             mem = interval([(start, stop-1)])
             var_interval += mem
         base_to_interval[addr] = var_interval
@@ -1033,7 +1035,7 @@ def retrieve_stack_accesses(ir_arch_a, ircfg):
         tmp += mem
 
     base_to_info = {}
-    for addr, vars in base_to_var.iteritems():
+    for addr, vars in viewitems(base_to_var):
         name = "var_%d" % (len(base_to_info))
         size = max([var.size for var in vars])
         base_to_info[addr] = size, name
@@ -1079,11 +1081,11 @@ def replace_stack_vars(ir_arch_a, ircfg):
 
     base_to_info = retrieve_stack_accesses(ir_arch_a, ircfg)
     modified = False
-    for block in ircfg.blocks.itervalues():
+    for block in list(viewvalues(ircfg.blocks)):
         assignblks = []
         for assignblk in block:
             out = {}
-            for dst, src in assignblk.iteritems():
+            for dst, src in viewitems(assignblk):
                 new_dst = dst.visit(lambda expr:replace_mem_stack_vars(expr, base_to_info))
                 new_src = src.visit(lambda expr:replace_mem_stack_vars(expr, base_to_info))
                 if new_dst != dst or new_src != src:
@@ -1120,9 +1122,9 @@ def get_memlookup(expr, bs, is_addr_ro_variable):
 
 def read_mem(bs, expr):
     ptr = int(expr.ptr)
-    var_bytes = bs.getbytes(ptr, expr.size / 8)[::-1]
+    var_bytes = bs.getbytes(ptr, expr.size // 8)[::-1]
     try:
-        value = int(var_bytes.encode('hex'), 16)
+        value = int(encode_hex(var_bytes), 16)
     except ValueError:
         return expr
     return ExprInt(value, expr.size)
@@ -1137,11 +1139,11 @@ def load_from_int(ir_arch, bs, is_addr_ro_variable):
     """
 
     modified = False
-    for block in ir_arch.blocks.itervalues():
+    for block in list(viewvalues(ir_arch.blocks)):
         assignblks = list()
         for assignblk in block:
             out = {}
-            for dst, src in assignblk.iteritems():
+            for dst, src in viewitems(assignblk):
                 # Test src
                 mems = get_memlookup(src, bs, is_addr_ro_variable)
                 src_new = src
@@ -1197,7 +1199,7 @@ class AssignBlockLivenessInfos(object):
         out.append(
             '\n'.join(
                 "\t%s = %s" % (dst, src)
-                for (dst, src) in self.assignblk.iteritems()
+                for (dst, src) in viewitems(self.assignblk)
             )
         )
         out.append("\tVarOut:" + ", ".join(str(x) for x in self.var_out))
@@ -1217,7 +1219,7 @@ class IRBlockLivenessInfos(object):
         self.assignblks = []
         for assignblk in irblock:
             gens, kills = set(), set()
-            for dst, src in assignblk.iteritems():
+            for dst, src in viewitems(assignblk):
                 expr = ExprAssign(dst, src)
                 read = expr.get_r(mem_read=True)
                 write = expr.get_w()
@@ -1290,13 +1292,13 @@ class DiGraphLiveness(DiGraph):
         )
         if node not in self._blocks:
             yield [self.DotCellDescription(text="NOT PRESENT", attr={})]
-            raise StopIteration
+            return
 
         for i, info in enumerate(self._blocks[node].infos):
             var_in = "VarIn:" + ", ".join(str(x) for x in info.var_in)
             var_out = "VarOut:" + ", ".join(str(x) for x in info.var_out)
 
-            assignmnts = ["%s = %s" % (dst, src) for (dst, src) in info.assignblk.iteritems()]
+            assignmnts = ["%s = %s" % (dst, src) for (dst, src) in viewitems(info.assignblk)]
 
             if i == 0:
                 yield self.DotCellDescription(
@@ -1323,7 +1325,7 @@ class DiGraphLiveness(DiGraph):
         """
         infos = block.infos
         modified = False
-        for i in reversed(xrange(len(infos))):
+        for i in reversed(range(len(infos))):
             new_vars = set(infos[i].gen.union(infos[i].var_out.difference(infos[i].kill)))
             if infos[i].var_in != new_vars:
                 modified = True
@@ -1385,13 +1387,13 @@ def discard_phi_sources(ircfg, deleted_vars):
     @ircfg: IRCFG instance in ssa form
     @deleted_vars: unused phi sources
     """
-    for block in ircfg.blocks.values():
+    for block in list(viewvalues(ircfg.blocks)):
         if not block.assignblks:
             continue
         assignblk = block[0]
         todo = {}
         modified = False
-        for dst, src in assignblk.iteritems():
+        for dst, src in viewitems(assignblk):
             if not src.is_op('Phi'):
                 todo[dst] = src
                 continue
@@ -1459,7 +1461,7 @@ def update_phi_with_deleted_edges(ircfg, edges_to_del):
         assignblks = list(block)
         assignblk = assignblks[0]
         out = {}
-        for dst, phi_sources in assignblk.iteritems():
+        for dst, phi_sources in viewitems(assignblk):
             if not phi_sources.is_op('Phi'):
                 out = assignblk
                 break
@@ -1484,7 +1486,7 @@ def update_phi_with_deleted_edges(ircfg, edges_to_del):
         new_irblock = IRBlock(loc_dst, assignblks)
         blocks[block.loc_key] = new_irblock
 
-    for loc_key, block in blocks.iteritems():
+    for loc_key, block in viewitems(blocks):
         ircfg.blocks[loc_key] = block
     return modified
 
@@ -1543,13 +1545,13 @@ class DiGraphLivenessSSA(DiGraphLivenessIRA):
         super(DiGraphLivenessSSA, self).__init__(ircfg)
 
         self.loc_key_to_phi_parents = {}
-        for irblock in self.blocks.values():
+        for irblock in viewvalues(self.blocks):
             if not irblock_has_phi(irblock):
                 continue
             out = {}
-            for sources in irblock[0].itervalues():
+            for sources in viewvalues(irblock[0]):
                 var_to_parents = get_phi_sources_parent_block(self, irblock.loc_key, sources.args)
-                for var, var_parents in var_to_parents.iteritems():
+                for var, var_parents in viewitems(var_to_parents):
                     out.setdefault(var, set()).update(var_parents)
             self.loc_key_to_phi_parents[irblock.loc_key] = out
 
diff --git a/miasm2/analysis/debugging.py b/miasm2/analysis/debugging.py
index 6b88f00a..824b62ce 100644
--- a/miasm2/analysis/debugging.py
+++ b/miasm2/analysis/debugging.py
@@ -1,11 +1,16 @@
+from __future__ import print_function
+from builtins import map
+from builtins import range
 import cmd
+from future.utils import viewitems
+
 from miasm2.core.utils import hexdump
 from miasm2.core.interval import interval
 import miasm2.jitter.csts as csts
 from miasm2.jitter.jitload import ExceptionHandle
 
 
-class DebugBreakpoint:
+class DebugBreakpoint(object):
 
     "Debug Breakpoint parent class"
     pass
@@ -46,17 +51,19 @@ class DebugBreakpointMemory(DebugBreakpoint):
 
     def __str__(self):
         bp_type = ""
-        for k, v in self.type2str.items():
+        for k, v in viewitems(self.type2str):
             if k & self.access_type != 0:
                 bp_type += v
-        return "Memory BP @0x%08x, Size 0x%08x, Type %s" % (self.addr,
-                                                            self.size,
-                                                            bp_type)
+        return "Memory BP @0x%08x, Size 0x%08x, Type %s" % (
+            self.addr,
+            self.size,
+            bp_type
+        )
 
     @classmethod
     def get_access_type(cls, read=False, write=False):
         value = 0
-        for k, v in cls.type2str.items():
+        for k, v in viewitems(cls.type2str):
             if v == "R" and read is True:
                 value += k
             if v == "W" and write is True:
@@ -146,10 +153,10 @@ class Debugguer(object):
             return DebugBreakpointTerminate(res)
 
         if isinstance(res, DebugBreakpointSoft):
-            print "Breakpoint reached @0x%08x" % res.addr
+            print("Breakpoint reached @0x%08x" % res.addr)
         elif isinstance(res, ExceptionHandle):
             if res == ExceptionHandle.memoryBreakpoint():
-                print "Memory breakpoint reached!"
+                print("Memory breakpoint reached!")
 
                 # Remove flag
                 except_flag = self.myjit.vm.get_exception()
@@ -196,7 +203,7 @@ class Debugguer(object):
 
     def on_step(self):
         for addr, size in self.mem_watched:
-            print "@0x%08x:" % addr
+            print("@0x%08x:" % addr)
             self.get_mem(addr, size)
 
     def get_reg_value(self, reg_name):
@@ -238,20 +245,20 @@ class DebugCmd(cmd.Cmd, object):
     def print_breakpoints(self):
         bp_list = self.dbg.bp_list
         if len(bp_list) == 0:
-            print "No breakpoints."
+            print("No breakpoints.")
         else:
             for i, b in enumerate(bp_list):
-                print "%d\t0x%08x" % (i, b.addr)
+                print("%d\t0x%08x" % (i, b.addr))
 
     def print_watchmems(self):
         watch_list = self.dbg.mem_watched
         if len(watch_list) == 0:
-            print "No memory watchpoints."
+            print("No memory watchpoints.")
         else:
-            print "Num\tAddress  \tSize"
+            print("Num\tAddress  \tSize")
             for i, w in enumerate(watch_list):
                 addr, size = w
-                print "%d\t0x%08x\t0x%08x" % (i, addr, size)
+                print("%d\t0x%08x\t0x%08x" % (i, addr, size))
 
     def print_registers(self):
         regs = self.dbg.get_gpreg_all()
@@ -259,17 +266,21 @@ class DebugCmd(cmd.Cmd, object):
         # Display settings
         title1 = "Registers"
         title2 = "Values"
-        max_name_len = max(map(len, regs.keys() + [title1]))
+        max_name_len = max(map(len, list(regs) + [title1]))
 
         # Print value table
         s = "%s%s    |    %s" % (
             title1, " " * (max_name_len - len(title1)), title2)
-        print s
-        print "-" * len(s)
-        for name, value in sorted(regs.items(), key=lambda x: x[0]):
-            print "%s%s    |    %s" % (name,
-                                       " " * (max_name_len - len(name)),
-                                       hex(value).replace("L", ""))
+        print(s)
+        print("-" * len(s))
+        for name, value in sorted(viewitems(regs), key=lambda x: x[0]):
+            print(
+                "%s%s    |    %s" % (
+                    name,
+                    " " * (max_name_len - len(name)),
+                    hex(value).replace("L", "")
+                )
+            )
 
     def add_breakpoints(self, bp_addr):
         for addr in bp_addr:
@@ -281,35 +292,41 @@ class DebugCmd(cmd.Cmd, object):
                     good = False
                     break
             if good is False:
-                print "Breakpoint 0x%08x already set (%d)" % (addr, i)
+                print("Breakpoint 0x%08x already set (%d)" % (addr, i))
             else:
                 l = len(self.dbg.bp_list)
                 self.dbg.add_breakpoint(addr)
-                print "Breakpoint 0x%08x successfully added ! (%d)" % (addr, l)
+                print("Breakpoint 0x%08x successfully added ! (%d)" % (addr, l))
 
-    display_mode = {"mn": None,
-                    "regs": None,
-                    "newbloc": None}
+    display_mode = {
+        "mn": None,
+        "regs": None,
+        "newbloc": None
+    }
 
     def update_display_mode(self):
-        self.display_mode = {"mn": self.dbg.myjit.jit.log_mn,
-                             "regs": self.dbg.myjit.jit.log_regs,
-                             "newbloc": self.dbg.myjit.jit.log_newbloc}
+        self.display_mode = {
+            "mn": self.dbg.myjit.jit.log_mn,
+            "regs": self.dbg.myjit.jit.log_regs,
+            "newbloc": self.dbg.myjit.jit.log_newbloc
+        }
 
     # Command line methods
     def print_warning(self, s):
-        print self.color_r + s + self.color_e
+        print(self.color_r + s + self.color_e)
 
     def onecmd(self, line):
-        cmd_translate = {"h": "help",
-                         "q": "exit",
-                         "e": "exit",
-                         "!": "exec",
-                         "r": "run",
-                         "i": "info",
-                         "b": "breakpoint",
-                         "s": "step",
-                         "d": "dump"}
+        cmd_translate = {
+            "h": "help",
+            "q": "exit",
+            "e": "exit",
+            "!": "exec",
+            "r": "run",
+            "i": "info",
+            "b": "breakpoint",
+            "s": "step",
+            "d": "dump"
+        }
 
         if len(line) >= 2 and \
            line[1] == " " and \
@@ -342,12 +359,12 @@ class DebugCmd(cmd.Cmd, object):
         self.update_display_mode()
 
     def help_display(self):
-        print "Enable/Disable tracing."
-        print "Usage: display <mode1> <mode2> ... on|off"
-        print "Available modes are:"
+        print("Enable/Disable tracing.")
+        print("Usage: display <mode1> <mode2> ... on|off")
+        print("Available modes are:")
         for k in self.display_mode:
-            print "\t%s" % k
-        print "Use 'info display' to get current values"
+            print("\t%s" % k)
+        print("Use 'info display' to get current values")
 
     def do_watchmem(self, arg):
         if arg == "":
@@ -365,21 +382,23 @@ class DebugCmd(cmd.Cmd, object):
         self.dbg.watch_mem(addr, size)
 
     def help_watchmem(self):
-        print "Add a memory watcher."
-        print "Usage: watchmem <addr> [size]"
-        print "Use 'info watchmem' to get current memory watchers"
+        print("Add a memory watcher.")
+        print("Usage: watchmem <addr> [size]")
+        print("Use 'info watchmem' to get current memory watchers")
 
     def do_info(self, arg):
-        av_info = ["registers",
-                   "display",
-                   "breakpoints",
-                   "watchmem"]
+        av_info = [
+            "registers",
+            "display",
+            "breakpoints",
+            "watchmem"
+        ]
 
         if arg == "":
-            print "'info' must be followed by the name of an info command."
-            print "List of info subcommands:"
+            print("'info' must be followed by the name of an info command.")
+            print("List of info subcommands:")
             for k in av_info:
-                print "\t%s" % k
+                print("\t%s" % k)
 
         if arg.startswith("b"):
             # Breakpoint
@@ -388,8 +407,8 @@ class DebugCmd(cmd.Cmd, object):
         if arg.startswith("d"):
             # Display
             self.update_display_mode()
-            for k, v in self.display_mode.items():
-                print "%s\t\t%s" % (k, v)
+            for k, v in viewitems(self.display_mode):
+                print("%s\t\t%s" % (k, v))
 
         if arg.startswith("w"):
             # Watchmem
@@ -400,9 +419,9 @@ class DebugCmd(cmd.Cmd, object):
             self.print_registers()
 
     def help_info(self):
-        print "Generic command for showing things about the program being"
-        print "debugged. Use 'info' without arguments to get the list of"
-        print "available subcommands."
+        print("Generic command for showing things about the program being")
+        print("debugged. Use 'info' without arguments to get the list of")
+        print("available subcommands.")
 
     def do_breakpoint(self, arg):
         if arg == "":
@@ -412,23 +431,23 @@ class DebugCmd(cmd.Cmd, object):
             self.add_breakpoints(addrs)
 
     def help_breakpoint(self):
-        print "Add breakpoints to argument addresses."
-        print "Example:"
-        print "\tbreakpoint 0x11223344"
-        print "\tbreakpoint 1122 0xabcd"
+        print("Add breakpoints to argument addresses.")
+        print("Example:")
+        print("\tbreakpoint 0x11223344")
+        print("\tbreakpoint 1122 0xabcd")
 
     def do_step(self, arg):
         if arg == "":
             nb = 1
         else:
             nb = int(arg)
-        for _ in xrange(nb):
+        for _ in range(nb):
             self.dbg.step()
 
     def help_step(self):
-        print "Step program until it reaches a different source line."
-        print "Argument N means do this N times (or till program stops"
-        print "for another reason)."
+        print("Step program until it reaches a different source line.")
+        print("Argument N means do this N times (or till program stops")
+        print("for another reason).")
 
     def do_dump(self, arg):
         if arg == "":
@@ -444,36 +463,36 @@ class DebugCmd(cmd.Cmd, object):
             self.dbg.get_mem(addr, size)
 
     def help_dump(self):
-        print "Dump <addr> [size]. Dump size bytes at addr."
+        print("Dump <addr> [size]. Dump size bytes at addr.")
 
     def do_run(self, _):
         self.dbg.run()
 
     def help_run(self):
-        print "Launch or continue the current program"
+        print("Launch or continue the current program")
 
     def do_exit(self, _):
         return True
 
     def do_exec(self, line):
         try:
-            print eval(line)
-        except Exception, error:
-            print "*** Error: %s" % error
+            print(eval(line))
+        except Exception as error:
+            print("*** Error: %s" % error)
 
     def help_exec(self):
-        print "Exec a python command."
-        print "You can also use '!' shortcut."
+        print("Exec a python command.")
+        print("You can also use '!' shortcut.")
 
     def help_exit(self):
-        print "Exit the interpreter."
-        print "You can also use the Ctrl-D shortcut."
+        print("Exit the interpreter.")
+        print("You can also use the Ctrl-D shortcut.")
 
     def help_help(self):
-        print "Print help"
+        print("Print help")
 
     def postloop(self):
-        print '\nGoodbye !'
+        print('\nGoodbye !')
         super(DebugCmd, self).postloop()
 
     do_EOF = do_exit
diff --git a/miasm2/analysis/depgraph.py b/miasm2/analysis/depgraph.py
index 4e5f0433..4bfae67f 100644
--- a/miasm2/analysis/depgraph.py
+++ b/miasm2/analysis/depgraph.py
@@ -1,5 +1,9 @@
 """Provide dependency graph"""
 
+from functools import total_ordering
+
+from future.utils import viewitems
+
 from miasm2.expression.expression import ExprInt, ExprLoc, ExprAssign
 from miasm2.core.graph import DiGraph
 from miasm2.core.locationdb import LocationDB
@@ -14,7 +18,7 @@ try:
 except ImportError:
     pass
 
-
+@total_ordering
 class DependencyNode(object):
 
     """Node elements of a DependencyGraph
@@ -50,16 +54,17 @@ class DependencyNode(object):
                 self.element == depnode.element and
                 self.line_nb == depnode.line_nb)
 
-    def __ne__(self, other):
-        return not self.__eq__(other)
+    def __ne__(self, depnode):
+        # required Python 2.7.14
+        return not self == depnode
 
-    def __cmp__(self, node):
+    def __lt__(self, node):
         """Compares @self with @node."""
         if not isinstance(node, self.__class__):
-            return cmp(self.__class__, node.__class__)
+            return NotImplemented
 
-        return cmp((self.loc_key, self.element, self.line_nb),
-                   (node.loc_key, node.element, node.line_nb))
+        return ((self.loc_key, self.element, self.line_nb) <
+                (node.loc_key, node.element, node.line_nb))
 
     def __str__(self):
         """Returns a string representation of DependencyNode"""
@@ -96,7 +101,7 @@ class DependencyState(object):
     def __init__(self, loc_key, pending, line_nb=None):
         self.loc_key = loc_key
         self.history = [loc_key]
-        self.pending = {k: set(v) for k, v in pending.iteritems()}
+        self.pending = {k: set(v) for k, v in viewitems(pending)}
         self.line_nb = line_nb
         self.links = set()
 
@@ -104,9 +109,11 @@ class DependencyState(object):
         self._graph = None
 
     def __repr__(self):
-        return "<State: %r (%r) (%r)>" % (self.loc_key,
-                                          self.pending,
-                                          self.links)
+        return "<State: %r (%r) (%r)>" % (
+            self.loc_key,
+            self.pending,
+            self.links
+        )
 
     def extend(self, loc_key):
         """Return a copy of itself, with itself in history
@@ -129,7 +136,7 @@ class DependencyState(object):
                 graph.add_node(node_a)
             else:
                 graph.add_edge(node_a, node_b)
-        for parent, sons in self.pending.iteritems():
+        for parent, sons in viewitems(self.pending):
             for son in sons:
                 graph.add_edge(parent, son)
         return graph
@@ -148,7 +155,7 @@ class DependencyState(object):
 
     def add_pendings(self, future_pending):
         """Add @future_pending to the state"""
-        for node, depnodes in future_pending.iteritems():
+        for node, depnodes in viewitems(future_pending):
             if node not in self.pending:
                 self.pending[node] = depnodes
             else:
@@ -263,7 +270,7 @@ class DependencyResult(DependencyState):
             line2elements.setdefault(depnode.line_nb,
                                      set()).add(depnode.element)
 
-        for line_nb, elements in sorted(line2elements.iteritems()):
+        for line_nb, elements in sorted(viewitems(line2elements)):
             if max_line is not None and line_nb >= max_line:
                 break
             assignmnts = {}
@@ -385,8 +392,10 @@ class DependencyResultImplicit(DependencyResult):
         self._solver = solver
 
         # Return only inputs values (others could be wrongs)
-        return {element: symb_exec.eval_expr(element)
-                for element in self.inputs}
+        return {
+            element: symb_exec.eval_expr(element)
+            for element in self.inputs
+        }
 
     @property
     def is_satisfiable(self):
@@ -562,7 +571,7 @@ class DependencyGraph(object):
         """Track pending expression in an assignblock"""
         future_pending = {}
         node_resolved = set()
-        for dst, src in assignblk.iteritems():
+        for dst, src in viewitems(assignblk):
             # Only track pending
             if dst not in state.pending:
                 continue
diff --git a/miasm2/analysis/disasm_cb.py b/miasm2/analysis/disasm_cb.py
index d3278cb4..36e120b6 100644
--- a/miasm2/analysis/disasm_cb.py
+++ b/miasm2/analysis/disasm_cb.py
@@ -1,5 +1,9 @@
 #-*- coding:utf-8 -*-
 
+from __future__ import print_function
+
+from future.utils import viewvalues
+
 from miasm2.expression.expression import ExprInt, ExprId, ExprMem, match_expr
 from miasm2.expression.simplifications import expr_simp
 from miasm2.core.asmblock import AsmConstraintNext, AsmConstraintTo
@@ -27,13 +31,12 @@ def arm_guess_subcall(
     sp = LocationDB()
     ir_arch = ira(sp)
     ircfg = ira.new_ircfg()
-    print '###'
-    print cur_bloc
+    print('###')
+    print(cur_bloc)
     ir_arch.add_asmblock_to_ircfg(cur_bloc, ircfg)
 
-    ir_blocks = ircfg.blocks.values()
     to_add = set()
-    for irblock in ir_blocks:
+    for irblock in viewvalues(ircfg.blocks):
         pc_val = None
         lr_val = None
         for exprs in irblock:
@@ -72,8 +75,7 @@ def arm_guess_jump_table(
     ircfg = ira.new_ircfg()
     ir_arch.add_asmblock_to_ircfg(cur_bloc, ircfg)
 
-    ir_blocks = ircfg.blocks.values()
-    for irblock in ir_blocks:
+    for irblock in viewvalues(ircfg.blocks):
         pc_val = None
         for exprs in irblock:
             for e in exprs:
@@ -84,18 +86,18 @@ def arm_guess_jump_table(
         if not isinstance(pc_val, ExprMem):
             continue
         assert(pc_val.size == 32)
-        print pc_val
+        print(pc_val)
         ad = pc_val.arg
         ad = expr_simp(ad)
-        print ad
+        print(ad)
         res = match_expr(ad, jra + jrb, set([jra, jrb]))
         if res is False:
             raise NotImplementedError('not fully functional')
-        print res
+        print(res)
         if not isinstance(res[jrb], ExprInt):
             raise NotImplementedError('not fully functional')
         base_ad = int(res[jrb])
-        print base_ad
+        print(base_ad)
         addrs = set()
         i = -1
         max_table_entry = 10000
@@ -109,7 +111,7 @@ def arm_guess_jump_table(
             if abs(ad - base_ad) > max_diff_addr:
                 break
             addrs.add(ad)
-        print [hex(x) for x in addrs]
+        print([hex(x) for x in addrs])
 
         for ad in addrs:
             offsets_to_dis.add(ad)
diff --git a/miasm2/analysis/dse.py b/miasm2/analysis/dse.py
index 5eb924d7..fee85984 100644
--- a/miasm2/analysis/dse.py
+++ b/miasm2/analysis/dse.py
@@ -47,7 +47,7 @@ Here are a few remainings TODO:
    the solver for reducing the possible values thanks to its accumulated
    constraints.
 """
-
+from builtins import range
 from collections import namedtuple
 
 try:
@@ -55,6 +55,9 @@ try:
 except ImportError:
     z3 = None
 
+from future.utils import viewitems
+
+from miasm2.core.utils import encode_hex, force_bytes
 from miasm2.expression.expression import ExprMem, ExprInt, ExprCompose, \
     ExprAssign, ExprId, ExprLoc, LocKey
 from miasm2.core.bin_stream import bin_stream_vm
@@ -111,7 +114,7 @@ class ESETrackModif(EmulatedSymbExec):
 
         # Split access in atomic accesses
         out = []
-        for addr in xrange(dst_addr, dst_addr + (expr_mem.size / 8)):
+        for addr in range(dst_addr, dst_addr + expr_mem.size // 8):
             if addr in self.dse_memory_range:
                 # Symbolize memory access
                 out.append(self.dse_memory_to_expr(addr))
@@ -249,14 +252,18 @@ class DSEEngine(object):
 
         Known functions will be looked by {name}_symb in the @namespace
         """
+        namespace = dict(
+            (force_bytes(name), func) for name, func in viewitems(namespace)
+        )
 
         # lambda cannot contain statement
         def default_func(dse):
-            fname = "%s_symb" % libimp.fad2cname[dse.jitter.pc]
+            fname = b"%s_symb" % libimp.fad2cname[dse.jitter.pc]
             raise RuntimeError("Symbolic stub '%s' not found" % fname)
 
-        for addr, fname in libimp.fad2cname.iteritems():
-            fname = "%s_symb" % fname
+        for addr, fname in viewitems(libimp.fad2cname):
+            fname = force_bytes(fname)
+            fname = b"%s_symb" % fname
             func = namespace.get(fname, None)
             if func is not None:
                 self.add_handler(addr, func)
@@ -292,9 +299,11 @@ class DSEEngine(object):
                     if value != symb_value:
                         errors.append(DriftInfo(symbol, symb_value, value))
             elif symbol.is_mem() and symbol.ptr.is_int():
-                value_chr = self.jitter.vm.get_mem(int(symbol.ptr),
-                                                   symbol.size / 8)
-                exp_value = int(value_chr[::-1].encode("hex"), 16)
+                value_chr = self.jitter.vm.get_mem(
+                    int(symbol.ptr),
+                    symbol.size // 8
+                )
+                exp_value = int(encode_hex(value_chr[::-1]), 16)
                 if exp_value != symb_value:
                     errors.append(DriftInfo(symbol, symb_value, exp_value))
 
@@ -410,14 +419,16 @@ class DSEEngine(object):
         if memory:
             self.jitter.vm.reset_memory_page_pool()
             self.jitter.vm.reset_code_bloc_pool()
-            for addr, metadata in snapshot["mem"].iteritems():
-                self.jitter.vm.add_memory_page(addr,
-                                               metadata["access"],
-                                               metadata["data"])
+            for addr, metadata in viewitems(snapshot["mem"]):
+                self.jitter.vm.add_memory_page(
+                    addr,
+                    metadata["access"],
+                    metadata["data"]
+                )
 
         # Restore registers
         self.jitter.pc = snapshot["regs"][self.ir_arch.pc.name]
-        for reg, value in snapshot["regs"].iteritems():
+        for reg, value in viewitems(snapshot["regs"]):
             setattr(self.jitter.cpu, reg, value)
 
         # Reset intern elements
@@ -426,16 +437,16 @@ class DSEEngine(object):
         self.jitter.bs._atomic_mode = False
 
         # Reset symb exec
-        for key, _ in self.symb.symbols.items():
+        for key, _ in list(viewitems(self.symb.symbols)):
             del self.symb.symbols[key]
-        for expr, value in snapshot["symb"].items():
+        for expr, value in viewitems(snapshot["symb"]):
             self.symb.symbols[expr] = value
 
     def update_state(self, assignblk):
         """From this point, assume @assignblk in the symbolic execution
         @assignblk: AssignBlock/{dst -> src}
         """
-        for dst, src in assignblk.iteritems():
+        for dst, src in viewitems(assignblk):
             self.symb.apply_change(dst, src)
 
     def _update_state_from_concrete_symb(self, symbexec, cpu=True, mem=False):
@@ -534,8 +545,10 @@ class DSEPathConstraint(DSEEngine):
 
     def take_snapshot(self, *args, **kwargs):
         snap = super(DSEPathConstraint, self).take_snapshot(*args, **kwargs)
-        snap["new_solutions"] = {dst: src.copy
-                                 for dst, src in self.new_solutions.iteritems()}
+        snap["new_solutions"] = {
+            dst: src.copy
+            for dst, src in viewitems(self.new_solutions)
+        }
         snap["cur_constraints"] = self.cur_solver.assertions()
         if self._produce_solution_strategy == self.PRODUCE_SOLUTION_PATH_COV:
             snap["_history"] = list(self._history)
@@ -650,9 +663,11 @@ class DSEPathConstraint(DSEEngine):
                             # if addr (- [a, b], then @size[addr] reachables
                             # values are in @8[a, b + size[
                             for start, stop in addr_range:
-                                stop += (expr.size / 8) - 1
-                                full_range = ModularIntervals(symb_pc.size,
-                                                              [(start, stop)])
+                                stop += expr.size // 8 - 1
+                                full_range = ModularIntervals(
+                                    symb_pc.size,
+                                    [(start, stop)]
+                                )
                                 memory_to_add.update(full_range)
                     path_constraint.add(eaff)
 
@@ -662,7 +677,7 @@ class DSEPathConstraint(DSEEngine):
 
                 # Inject memory
                 for start, stop in memory_to_add:
-                    for address in xrange(start, stop + 1):
+                    for address in range(start, stop + 1):
                         expr_mem = ExprMem(ExprInt(address,
                                                    self.ir_arch.pc.size),
                                            8)
diff --git a/miasm2/analysis/expression_range.py b/miasm2/analysis/expression_range.py
index f09a18d0..8f498549 100644
--- a/miasm2/analysis/expression_range.py
+++ b/miasm2/analysis/expression_range.py
@@ -1,5 +1,8 @@
 """Naive range analysis for expression"""
 
+from future.builtins import zip
+from functools import reduce
+
 from miasm2.analysis.modularintervals import ModularIntervals
 
 _op_range_handler = {
@@ -44,9 +47,11 @@ def expr_range(expr):
         # Otherwise, overapproximate (ie. full range interval)
         if expr.op in _op_range_handler:
             sub_ranges = [expr_range(arg) for arg in expr.args]
-            return reduce(_op_range_handler[expr.op],
-                          (sub_range for sub_range in sub_ranges[1:]),
-                          sub_ranges[0])
+            return reduce(
+                _op_range_handler[expr.op],
+                (sub_range for sub_range in sub_ranges[1:]),
+                sub_ranges[0]
+            )
         elif expr.op == "-":
             assert len(expr.args) == 1
             return - expr_range(expr.args[0])
diff --git a/miasm2/analysis/gdbserver.py b/miasm2/analysis/gdbserver.py
index 6c630f88..61ee8955 100644
--- a/miasm2/analysis/gdbserver.py
+++ b/miasm2/analysis/gdbserver.py
@@ -1,10 +1,15 @@
 #-*- coding:utf-8 -*-
 
+from __future__ import print_function
+from future.builtins import map, range
+
+from miasm2.core.utils import decode_hex, encode_hex, int_to_byte
+
 import socket
 import struct
 import time
 import logging
-from StringIO import StringIO
+from io import BytesIO
 import miasm2.analysis.debugging as debugging
 from miasm2.jitter.jitload import ExceptionHandle
 
@@ -15,7 +20,7 @@ class GdbServer(object):
 
     general_registers_order = []
     general_registers_size = {}  # RegName : Size in octet
-    status = "S05"
+    status = b"S05"
 
     def __init__(self, dbg, port=4455):
         server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -28,242 +33,243 @@ class GdbServer(object):
     # Communication methods
 
     def compute_checksum(self, data):
-        return chr(sum(map(ord, data)) % 256).encode("hex")
+        return encode_hex(int_to_byte(sum(map(ord, data)) % 256))
 
     def get_messages(self):
-        all_data = ""
-        data = self.sock.recv(4096)
-        all_data += data
-        while (len(data) == 4096 or data == ""):
-            if data == "":
-                # Avoid consuming CPU
-                time.sleep(0.001)
-                continue
+        all_data = b""
+        while True:
             data = self.sock.recv(4096)
+            if not data:
+                break
             all_data += data
 
         logging.debug("<- %r", all_data)
         self.recv_queue += self.parse_messages(all_data)
 
     def parse_messages(self, data):
-        buf = StringIO(data)
-
+        buf = BytesIO(data)
         msgs = []
 
         while (buf.tell() < buf.len):
             token = buf.read(1)
-            if token == "+":
+            if token == b"+":
                 continue
-            if token == "-":
+            if token == b"-":
                 raise NotImplementedError("Resend packet")
-            if token == "$":
-                packet_data = ""
+            if token == b"$":
+                packet_data = b""
                 c = buf.read(1)
-                while c != "#":
+                while c != b"#":
                     packet_data += c
                     c = buf.read(1)
                 checksum = buf.read(2)
                 if checksum != self.compute_checksum(packet_data):
                     raise ValueError("Incorrect checksum")
-
                 msgs.append(packet_data)
 
         return msgs
 
     def send_string(self, s):
-        self.send_queue.append("O" + s.encode("hex"))
+        self.send_queue.append(b"O" + encode_hex(s))
 
     def process_messages(self):
 
         while self.recv_queue:
             msg = self.recv_queue.pop(0)
-            buf = StringIO(msg)
+            buf = BytesIO(msg)
             msg_type = buf.read(1)
 
-            self.send_queue.append("+")
+            self.send_queue.append(b"+")
 
-            if msg_type == "q":
-                if msg.startswith("qSupported"):
-                    self.send_queue.append("PacketSize=3fff")
-                elif msg.startswith("qC"):
+            if msg_type == b"q":
+                if msg.startswith(b"qSupported"):
+                    self.send_queue.append(b"PacketSize=3fff")
+                elif msg.startswith(b"qC"):
                     # Current thread
-                    self.send_queue.append("")
-                elif msg.startswith("qAttached"):
+                    self.send_queue.append(b"")
+                elif msg.startswith(b"qAttached"):
                     # Not supported
-                    self.send_queue.append("")
-                elif msg.startswith("qTStatus"):
+                    self.send_queue.append(b"")
+                elif msg.startswith(b"qTStatus"):
                     # Not supported
-                    self.send_queue.append("")
-                elif msg.startswith("qfThreadInfo"):
+                    self.send_queue.append(b"")
+                elif msg.startswith(b"qfThreadInfo"):
                     # Not supported
-                    self.send_queue.append("")
+                    self.send_queue.append(b"")
                 else:
                     raise NotImplementedError()
 
-            elif msg_type == "H":
+            elif msg_type == b"H":
                 # Set current thread
-                self.send_queue.append("OK")
+                self.send_queue.append(b"OK")
 
-            elif msg_type == "?":
+            elif msg_type == b"?":
                 # Report why the target halted
                 self.send_queue.append(self.status)  # TRAP signal
 
-            elif msg_type == "g":
+            elif msg_type == b"g":
                 # Report all general register values
                 self.send_queue.append(self.report_general_register_values())
 
-            elif msg_type == "p":
+            elif msg_type == b"p":
                 # Read a specific register
                 reg_num = int(buf.read(), 16)
                 self.send_queue.append(self.read_register(reg_num))
 
-            elif msg_type == "P":
+            elif msg_type == b"P":
                 # Set a specific register
-                reg_num, value = buf.read().split("=")
+                reg_num, value = buf.read().split(b"=")
                 reg_num = int(reg_num, 16)
-                value = int(value.decode("hex")[::-1].encode("hex"), 16)
+                value = int(encode_hex(decode_hex(value)[::-1]), 16)
                 self.set_register(reg_num, value)
-                self.send_queue.append("OK")
+                self.send_queue.append(b"OK")
 
-            elif msg_type == "m":
+            elif msg_type == b"m":
                 # Read memory
-                addr, size = map(lambda x: int(x, 16), buf.read().split(","))
+                addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
                 self.send_queue.append(self.read_memory(addr, size))
 
-            elif msg_type == "k":
+            elif msg_type == b"k":
                 # Kill
                 self.sock.close()
                 self.send_queue = []
                 self.sock = None
 
-            elif msg_type == "!":
+            elif msg_type == b"!":
                 # Extending debugging will be used
-                self.send_queue.append("OK")
+                self.send_queue.append(b"OK")
 
-            elif msg_type == "v":
-                if msg == "vCont?":
+            elif msg_type == b"v":
+                if msg == b"vCont?":
                     # Is vCont supported ?
-                    self.send_queue.append("")
+                    self.send_queue.append(b"")
 
-            elif msg_type == "s":
+            elif msg_type == b"s":
                 # Step
                 self.dbg.step()
-                self.send_queue.append("S05")  # TRAP signal
+                self.send_queue.append(b"S05")  # TRAP signal
 
-            elif msg_type == "Z":
+            elif msg_type == b"Z":
                 # Add breakpoint or watchpoint
                 bp_type = buf.read(1)
-                if bp_type == "0":
+                if bp_type == b"0":
                     # Exec breakpoint
-                    assert(buf.read(1) == ",")
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
+                    assert(buf.read(1) == b",")
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
 
                     if size != 1:
                         raise NotImplementedError("Bigger size")
                     self.dbg.add_breakpoint(addr)
-                    self.send_queue.append("OK")
+                    self.send_queue.append(b"OK")
 
-                elif bp_type == "1":
+                elif bp_type == b"1":
                     # Hardware BP
-                    assert(buf.read(1) == ",")
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
-
-                    self.dbg.add_memory_breakpoint(addr, size,
-                                                   read=True,
-                                                   write=True)
-                    self.send_queue.append("OK")
-
-                elif bp_type in ["2", "3", "4"]:
+                    assert(buf.read(1) == b",")
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
+
+                    self.dbg.add_memory_breakpoint(
+                        addr,
+                        size,
+                        read=True,
+                        write=True
+                    )
+                    self.send_queue.append(b"OK")
+
+                elif bp_type in [b"2", b"3", b"4"]:
                     # Memory breakpoint
-                    assert(buf.read(1) == ",")
-                    read = bp_type in ["3", "4"]
-                    write = bp_type in ["2", "4"]
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
-
-                    self.dbg.add_memory_breakpoint(addr, size,
-                                                   read=read,
-                                                   write=write)
-                    self.send_queue.append("OK")
+                    assert(buf.read(1) == b",")
+                    read = bp_type in [b"3", b"4"]
+                    write = bp_type in [b"2", b"4"]
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
+
+                    self.dbg.add_memory_breakpoint(
+                        addr,
+                        size,
+                        read=read,
+                        write=write
+                    )
+                    self.send_queue.append(b"OK")
 
                 else:
                     raise ValueError("Impossible value")
 
-            elif msg_type == "z":
+            elif msg_type == b"z":
                 # Remove breakpoint or watchpoint
                 bp_type = buf.read(1)
-                if bp_type == "0":
+                if bp_type == b"0":
                     # Exec breakpoint
-                    assert(buf.read(1) == ",")
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
+                    assert(buf.read(1) == b",")
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
 
                     if size != 1:
                         raise NotImplementedError("Bigger size")
                     dbgsoft = self.dbg.get_breakpoint_by_addr(addr)
                     assert(len(dbgsoft) == 1)
                     self.dbg.remove_breakpoint(dbgsoft[0])
-                    self.send_queue.append("OK")
+                    self.send_queue.append(b"OK")
 
-                elif bp_type == "1":
+                elif bp_type == b"1":
                     # Hardware BP
-                    assert(buf.read(1) == ",")
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
+                    assert(buf.read(1) == b",")
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
                     self.dbg.remove_memory_breakpoint_by_addr_access(
-                        addr, read=True, write=True)
-                    self.send_queue.append("OK")
+                        addr,
+                        read=True,
+                        write=True
+                    )
+                    self.send_queue.append(b"OK")
 
-                elif bp_type in ["2", "3", "4"]:
+                elif bp_type in [b"2", b"3", b"4"]:
                     # Memory breakpoint
-                    assert(buf.read(1) == ",")
-                    read = bp_type in ["3", "4"]
-                    write = bp_type in ["2", "4"]
-                    addr, size = map(
-                        lambda x: int(x, 16), buf.read().split(","))
+                    assert(buf.read(1) == b",")
+                    read = bp_type in [b"3", b"4"]
+                    write = bp_type in [b"2", b"4"]
+                    addr, size = (int(x, 16) for x in buf.read().split(b",", 1))
 
                     self.dbg.remove_memory_breakpoint_by_addr_access(
-                        addr, read=read, write=write)
-                    self.send_queue.append("OK")
+                        addr,
+                        read=read,
+                        write=write
+                    )
+                    self.send_queue.append(b"OK")
 
                 else:
                     raise ValueError("Impossible value")
 
-            elif msg_type == "c":
+            elif msg_type == b"c":
                 # Continue
-                self.status = ""
+                self.status = b""
                 self.send_messages()
                 ret = self.dbg.run()
                 if isinstance(ret, debugging.DebugBreakpointSoft):
-                    self.status = "S05"
-                    self.send_queue.append("S05")  # TRAP signal
+                    self.status = b"S05"
+                    self.send_queue.append(b"S05")  # TRAP signal
                 elif isinstance(ret, ExceptionHandle):
                     if ret == ExceptionHandle.memoryBreakpoint():
-                        self.status = "S05"
-                        self.send_queue.append("S05")
+                        self.status = b"S05"
+                        self.send_queue.append(b"S05")
                     else:
                         raise NotImplementedError("Unknown Except")
                 elif isinstance(ret, debugging.DebugBreakpointTerminate):
                     # Connexion should close, but keep it running as a TRAP
                     # The connexion will be close on instance destruction
-                    print ret
-                    self.status = "S05"
-                    self.send_queue.append("S05")
+                    print(ret)
+                    self.status = b"S05"
+                    self.send_queue.append(b"S05")
                 else:
                     raise NotImplementedError()
 
             else:
                 raise NotImplementedError(
-                    "Not implemented: message type '%s'" % msg_type)
+                    "Not implemented: message type %r" % msg_type
+                )
 
     def send_messages(self):
         for msg in self.send_queue:
-            if msg == "+":
-                data = "+"
+            if msg == b"+":
+                data = b"+"
             else:
-                data = "$%s#%s" % (msg, self.compute_checksum(msg))
+                data = b"$%s#%s" % (msg, self.compute_checksum(msg))
             logging.debug("-> %r", data)
             self.sock.send(data)
         self.send_queue = []
@@ -272,7 +278,7 @@ class GdbServer(object):
         self.recv_queue = []
         self.send_queue = []
 
-        self.send_string("Test\n")
+        self.send_string(b"Test\n")
 
         while (self.sock):
             self.get_messages()
@@ -285,8 +291,8 @@ class GdbServer(object):
 
     # Debugguer processing methods
     def report_general_register_values(self):
-        s = ""
-        for i in xrange(len(self.general_registers_order)):
+        s = b""
+        for i in range(len(self.general_registers_order)):
             s += self.read_register(i)
         return s
 
@@ -307,7 +313,7 @@ class GdbServer(object):
         else:
             raise NotImplementedError("Unknown size")
 
-        return struct.pack(pack_token, reg_value).encode("hex")
+        return encode_hex(struct.pack(pack_token, reg_value))
 
     def set_register(self, reg_num, value):
         reg_name = self.general_registers_order[reg_num]
@@ -319,39 +325,44 @@ class GdbServer(object):
     def read_memory(self, addr, size):
         except_flag_vm = self.dbg.myjit.vm.get_exception()
         try:
-            return self.dbg.get_mem_raw(addr, size).encode("hex")
+            return encode_hex(self.dbg.get_mem_raw(addr, size))
         except RuntimeError:
             self.dbg.myjit.vm.set_exception(except_flag_vm)
-            return "00" * size
+            return b"00" * size
 
 
 class GdbServer_x86_32(GdbServer):
 
     "Extend GdbServer for x86 32bits purposes"
 
-    general_registers_order = ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI",
-                               "EDI", "EIP", "EFLAGS", "CS", "SS", "DS", "ES",
-                               "FS", "GS"]
-
-    general_registers_size = {"EAX": 4,
-                              "ECX": 4,
-                              "EDX": 4,
-                              "EBX": 4,
-                              "ESP": 4,
-                              "EBP": 4,
-                              "ESI": 4,
-                              "EDI": 4,
-                              "EIP": 4,
-                              "EFLAGS": 2,
-                              "CS": 2,
-                              "SS": 2,
-                              "DS": 2,
-                              "ES": 2,
-                              "FS": 2,
-                              "GS": 2}
+    general_registers_order = [
+        "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI",
+        "EDI", "EIP", "EFLAGS", "CS", "SS", "DS", "ES",
+        "FS", "GS"
+    ]
+
+    general_registers_size = {
+        "EAX": 4,
+        "ECX": 4,
+        "EDX": 4,
+        "EBX": 4,
+        "ESP": 4,
+        "EBP": 4,
+        "ESI": 4,
+        "EDI": 4,
+        "EIP": 4,
+        "EFLAGS": 2,
+        "CS": 2,
+        "SS": 2,
+        "DS": 2,
+        "ES": 2,
+        "FS": 2,
+        "GS": 2
+    }
 
     register_ignore = [
-        "tf", "i_f", "nt", "rf", "vm", "ac", "vif", "vip", "i_d"]
+        "tf", "i_f", "nt", "rf", "vm", "ac", "vif", "vip", "i_d"
+    ]
 
     def read_register_by_name(self, reg_name):
         sup_func = super(GdbServer_x86_32, self).read_register_by_name
@@ -364,7 +375,8 @@ class GdbServer_x86_32(GdbServer):
         if reg_name == "EFLAGS":
             val = 0
             eflags_args = [
-                "cf", 1, "pf", 0, "af", 0, "zf", "nf", "tf", "i_f", "df", "of"]
+                "cf", 1, "pf", 0, "af", 0, "zf", "nf", "tf", "i_f", "df", "of"
+            ]
             eflags_args += ["nt", 0, "rf", "vm", "ac", "vif", "vip", "i_d"]
             eflags_args += [0] * 10
 
@@ -387,26 +399,30 @@ class GdbServer_msp430(GdbServer):
 
     "Extend GdbServer for msp430 purposes"
 
-    general_registers_order = ["PC", "SP", "SR", "R3", "R4", "R5", "R6", "R7",
-                               "R8", "R9", "R10", "R11", "R12", "R13", "R14",
-                               "R15"]
-
-    general_registers_size = {"PC": 2,
-                              "SP": 2,
-                              "SR": 2,
-                              "R3": 2,
-                              "R4": 2,
-                              "R5": 2,
-                              "R6": 2,
-                              "R7": 2,
-                              "R8": 2,
-                              "R9": 2,
-                              "R10": 2,
-                              "R11": 2,
-                              "R12": 2,
-                              "R13": 2,
-                              "R14": 2,
-                              "R15": 2}
+    general_registers_order = [
+        "PC", "SP", "SR", "R3", "R4", "R5", "R6", "R7",
+        "R8", "R9", "R10", "R11", "R12", "R13", "R14",
+        "R15"
+    ]
+
+    general_registers_size = {
+        "PC": 2,
+        "SP": 2,
+        "SR": 2,
+        "R3": 2,
+        "R4": 2,
+        "R5": 2,
+        "R6": 2,
+        "R7": 2,
+        "R8": 2,
+        "R9": 2,
+        "R10": 2,
+        "R11": 2,
+        "R12": 2,
+        "R13": 2,
+        "R14": 2,
+        "R15": 2
+    }
 
     def read_register_by_name(self, reg_name):
         sup_func = super(GdbServer_msp430, self).read_register_by_name
diff --git a/miasm2/analysis/modularintervals.py b/miasm2/analysis/modularintervals.py
index 83890f19..2195598b 100644
--- a/miasm2/analysis/modularintervals.py
+++ b/miasm2/analysis/modularintervals.py
@@ -1,4 +1,7 @@
 """Intervals with a maximum size, supporting modular arithmetic"""
+
+from future.builtins import range
+from builtins import int as int_types
 from itertools import product
 
 from miasm2.core.interval import interval
@@ -59,7 +62,7 @@ class ModularIntervals(object):
         """Check and promote the second argument from integer to
         ModularIntervals with one value"""
         def ret_func(self, target):
-            if isinstance(target, (int, long)):
+            if isinstance(target, int_types):
                 target = ModularIntervals(self.size, interval([(target, target)]))
             if not isinstance(target, ModularIntervals):
                 raise TypeError("Unsupported operation with %s" % target.__class__)
@@ -336,7 +339,7 @@ class ModularIntervals(object):
         shifter &= interval([(0, self.size)])
         ret = interval()
         for shift_range in shifter:
-            for shift in xrange(shift_range[0], shift_range[1] + 1):
+            for shift in range(shift_range[0], shift_range[1] + 1):
                 for x_min, x_max in self.intervals:
                     ret += self._range_shift_uniq(x_min, x_max, shift, operation)
         return self.__class__(self.size, ret)
@@ -372,7 +375,7 @@ class ModularIntervals(object):
         shifter %= self.size
         ret = interval()
         for shift_range in shifter:
-            for shift in xrange(shift_range[0], shift_range[1] + 1):
+            for shift in range(shift_range[0], shift_range[1] + 1):
                 for x_min, x_max in self.intervals:
                     ret += self._range_rotate_uniq(x_min, x_max, shift,
                                                    operation)
@@ -446,7 +449,7 @@ class ModularIntervals(object):
         @modulo: integer
         """
 
-        if not isinstance(modulo, (int, long)):
+        if not isinstance(modulo, int_types):
             raise TypeError("Modulo with %s is not supported" % modulo.__class__)
         return self._integer_modulo(modulo)
 
diff --git a/miasm2/analysis/outofssa.py b/miasm2/analysis/outofssa.py
index 6355aeb2..41c665af 100644
--- a/miasm2/analysis/outofssa.py
+++ b/miasm2/analysis/outofssa.py
@@ -1,3 +1,5 @@
+from future.utils import viewitems, viewvalues
+
 from miasm2.expression.expression import ExprId
 from miasm2.ir.ir import IRBlock, AssignBlock
 from miasm2.analysis.ssa import get_phi_sources_parent_block, \
@@ -59,7 +61,7 @@ class UnSSADiGraph(object):
         """
         ircfg = self.ssa.graph
 
-        for irblock in ircfg.blocks.values():
+        for irblock in list(viewvalues(ircfg.blocks)):
             if not irblock_has_phi(irblock):
                 continue
 
@@ -82,7 +84,7 @@ class UnSSADiGraph(object):
                 for parent, src in self.phi_parent_sources[dst]:
                     parent_to_parallel_copies.setdefault(parent, {})[new_var] = src
 
-            for parent, parallel_copies in parent_to_parallel_copies.iteritems():
+            for parent, parallel_copies in viewitems(parent_to_parallel_copies):
                 parent = ircfg.blocks[parent]
                 assignblks = list(parent)
                 assignblks.append(AssignBlock(parallel_copies, parent[-1].instr))
@@ -104,10 +106,10 @@ class UnSSADiGraph(object):
         node
         """
         ircfg = self.ssa.graph
-        for irblock in ircfg.blocks.itervalues():
+        for irblock in viewvalues(ircfg.blocks):
             if not irblock_has_phi(irblock):
                 continue
-            for dst, sources in irblock[0].iteritems():
+            for dst, sources in viewitems(irblock[0]):
                 assert sources.is_op('Phi')
                 new_var = self.create_copy_var(dst)
                 self.phi_new_var[dst] = new_var
@@ -130,7 +132,7 @@ class UnSSADiGraph(object):
         """
         Generate trivial coalescing of phi variable and itself
         """
-        for phi_new_var in self.phi_new_var.itervalues():
+        for phi_new_var in viewvalues(self.phi_new_var):
             self.merge_state.setdefault(phi_new_var, set([phi_new_var]))
 
     def order_ssa_var_dom(self):
@@ -303,7 +305,7 @@ class UnSSADiGraph(object):
         assignments.
         @parent: Optional parent location of the phi source for liveness tests
         """
-        for dst, src in parallel_copies.iteritems():
+        for dst, src in viewitems(parallel_copies):
             dst_merge = self.merge_state.setdefault(dst, set([dst]))
             src_merge = self.merge_state.setdefault(src, set([src]))
             if not self.merge_sets_interfere(dst_merge, src_merge, parent):
@@ -317,7 +319,7 @@ class UnSSADiGraph(object):
         ircfg = self.ssa.graph
 
         # Run coalesce on the post phi parallel copy
-        for irblock in ircfg.blocks.values():
+        for irblock in viewvalues(ircfg.blocks):
             if not irblock_has_phi(irblock):
                 continue
             parallel_copies = {}
@@ -335,7 +337,7 @@ class UnSSADiGraph(object):
                 for parent, src in self.phi_parent_sources[dst]:
                     parent_to_parallel_copies.setdefault(parent, {})[new_var] = src
 
-            for parent, parallel_copies in parent_to_parallel_copies.iteritems():
+            for parent, parallel_copies in viewitems(parent_to_parallel_copies):
                 self.aggressive_coalesce_parallel_copy(parallel_copies, parent)
 
     def get_best_merge_set_name(self, merge_set):
@@ -363,7 +365,7 @@ class UnSSADiGraph(object):
 
         # Elect representative for merge sets
         merge_set_to_name = {}
-        for merge_set in self.merge_state.itervalues():
+        for merge_set in viewvalues(self.merge_state):
             frozen_merge_set = frozenset(merge_set)
             merge_sets.add(frozen_merge_set)
             var_name = self.get_best_merge_set_name(merge_set)
@@ -384,10 +386,10 @@ class UnSSADiGraph(object):
         @ircfg: IRDiGraph instance
         """
 
-        for irblock in self.ssa.graph.blocks.values():
+        for irblock in list(viewvalues(self.ssa.graph.blocks)):
             assignblks = list(irblock)
             out = {}
-            for dst, src in assignblks[0].iteritems():
+            for dst, src in viewitems(assignblks[0]):
                 if src.is_op('Phi'):
                     assert set([dst]) == set(src.args)
                     continue
@@ -399,11 +401,11 @@ class UnSSADiGraph(object):
         """
         Remove trivial expressions (a=a) in the current graph
         """
-        for irblock in self.ssa.graph.blocks.values():
+        for irblock in list(viewvalues(self.ssa.graph.blocks)):
             assignblks = list(irblock)
             for i, assignblk in enumerate(assignblks):
                 out = {}
-                for dst, src in assignblk.iteritems():
+                for dst, src in viewitems(assignblk):
                     if dst == src:
                         continue
                     out[dst] = src
diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py
index ccffd529..d3e8fce1 100644
--- a/miasm2/analysis/sandbox.py
+++ b/miasm2/analysis/sandbox.py
@@ -1,13 +1,20 @@
+from __future__ import print_function
+from builtins import range
+
 import os
 import logging
 from argparse import ArgumentParser
 
+from future.utils import viewitems, viewvalues
+
+from miasm2.core.utils import force_bytes
 from miasm2.analysis.machine import Machine
 from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE
 from miasm2.analysis import debugging
 from miasm2.jitter.jitload import log_func
 
 
+
 class Sandbox(object):
 
     """
@@ -112,7 +119,7 @@ class Sandbox(object):
 
             if self.options.gdbserver:
                 port = self.options.gdbserver
-                print "Listen on port %d" % port
+                print("Listen on port %d" % port)
                 gdb = self.machine.gdbserver(dbg, port)
                 self.gdb = gdb
                 gdb.run()
@@ -184,7 +191,7 @@ class OS_Win(OS):
         from miasm2.jitter.loader.pe import vm_load_pe, vm_load_pe_libs,\
             preload_pe, libimp_pe, vm_load_pe_and_dependencies
         from miasm2.os_dep import win_api_x86_32, win_api_x86_32_seh
-        methods = win_api_x86_32.__dict__
+        methods = dict((name.encode(),func) for name, func in viewitems(win_api_x86_32.__dict__))
         methods.update(custom_methods)
 
         super(OS_Win, self).__init__(methods, *args, **kwargs)
@@ -199,33 +206,42 @@ class OS_Win(OS):
 
         # Load main pe
         with open(self.fname, "rb") as fstream:
-            self.pe = vm_load_pe(self.jitter.vm, fstream.read(),
-                                 load_hdr=self.options.load_hdr,
-                                 name=self.fname,
-                                 **kwargs)
+            self.pe = vm_load_pe(
+                self.jitter.vm,
+                fstream.read(),
+                load_hdr=self.options.load_hdr,
+                name=self.fname,
+                **kwargs
+            )
             self.name2module[fname_basename] = self.pe
 
         # Load library
         if self.options.loadbasedll:
 
             # Load libs in memory
-            self.name2module.update(vm_load_pe_libs(self.jitter.vm,
-                                                    self.ALL_IMP_DLL,
-                                                    libs,
-                                                    self.modules_path,
-                                                    **kwargs))
+            self.name2module.update(
+                vm_load_pe_libs(
+                    self.jitter.vm,
+                    self.ALL_IMP_DLL,
+                    libs,
+                    self.modules_path,
+                    **kwargs
+                )
+            )
 
             # Patch libs imports
-            for pe in self.name2module.itervalues():
+            for pe in viewvalues(self.name2module):
                 preload_pe(self.jitter.vm, pe, libs)
 
         if self.options.dependencies:
-            vm_load_pe_and_dependencies(self.jitter.vm,
-                                        fname_basename,
-                                        self.name2module,
-                                        libs,
-                                        self.modules_path,
-                                        **kwargs)
+            vm_load_pe_and_dependencies(
+                self.jitter.vm,
+                fname_basename,
+                self.name2module,
+                libs,
+                self.modules_path,
+                **kwargs
+            )
 
         win_api_x86_32.winobjs.current_pe = self.pe
 
@@ -275,8 +291,12 @@ class OS_Linux(OS):
         self.libs = libimp_elf()
 
         with open(self.fname, "rb") as fstream:
-            self.elf = vm_load_elf(self.jitter.vm, fstream.read(),
-                                   name=self.fname, **kwargs)
+            self.elf = vm_load_elf(
+                self.jitter.vm,
+                fstream.read(),
+                name=self.fname,
+                **kwargs
+            )
         preload_elf(self.jitter.vm, self.elf, self.libs)
 
         self.entry_point = self.elf.Ehdr.entry
@@ -325,7 +345,8 @@ class OS_Linux_str(OS):
         self.options.load_base_addr = int(self.options.load_base_addr, 0)
         self.jitter.vm.add_memory_page(
             self.options.load_base_addr, PAGE_READ | PAGE_WRITE, data,
-            "Initial Str")
+            "Initial Str"
+        )
 
         # Library calls handler
         self.jitter.add_lib_handler(libs, methods)
@@ -516,14 +537,17 @@ class Sandbox_Win_x86_64(Sandbox, Arch_x86_64, OS_Win):
         Sandbox.__init__(self, *args, **kwargs)
 
         # reserve stack for local reg
-        for _ in xrange(0x4):
+        for _ in range(0x4):
             self.jitter.push_uint64_t(0)
 
         # Pre-stack return address
         self.jitter.push_uint64_t(self.CALL_FINISH_ADDR)
 
         # Set the runtime guard
-        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle)
+        self.jitter.add_breakpoint(
+            self.CALL_FINISH_ADDR,
+            self.__class__.code_sentinelle
+        )
 
     def run(self, addr=None):
         """
@@ -552,14 +576,16 @@ class Sandbox_Linux_x86_32(Sandbox, Arch_x86_32, OS_Linux):
         if self.options.mimic_env:
             env_ptrs = []
             for env in self.envp:
-                env += "\x00"
+                env = force_bytes(env)
+                env += b"\x00"
                 self.jitter.cpu.ESP -= len(env)
                 ptr = self.jitter.cpu.ESP
                 self.jitter.vm.set_mem(ptr, env)
                 env_ptrs.append(ptr)
             argv_ptrs = []
             for arg in self.argv:
-                arg += "\x00"
+                arg = force_bytes(arg)
+                arg += b"\x00"
                 self.jitter.cpu.ESP -= len(arg)
                 ptr = self.jitter.cpu.ESP
                 self.jitter.vm.set_mem(ptr, arg)
@@ -577,7 +603,10 @@ class Sandbox_Linux_x86_32(Sandbox, Arch_x86_32, OS_Linux):
             self.jitter.push_uint32_t(self.CALL_FINISH_ADDR)
 
         # Set the runtime guard
-        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle)
+        self.jitter.add_breakpoint(
+            self.CALL_FINISH_ADDR,
+            self.__class__.code_sentinelle
+        )
 
     def run(self, addr=None):
         """
@@ -607,14 +636,16 @@ class Sandbox_Linux_x86_64(Sandbox, Arch_x86_64, OS_Linux):
         if self.options.mimic_env:
             env_ptrs = []
             for env in self.envp:
-                env += "\x00"
+                env = force_bytes(env)
+                env += b"\x00"
                 self.jitter.cpu.RSP -= len(env)
                 ptr = self.jitter.cpu.RSP
                 self.jitter.vm.set_mem(ptr, env)
                 env_ptrs.append(ptr)
             argv_ptrs = []
             for arg in self.argv:
-                arg += "\x00"
+                arg = force_bytes(arg)
+                arg += b"\x00"
                 self.jitter.cpu.RSP -= len(arg)
                 ptr = self.jitter.cpu.RSP
                 self.jitter.vm.set_mem(ptr, arg)
@@ -632,7 +663,10 @@ class Sandbox_Linux_x86_64(Sandbox, Arch_x86_64, OS_Linux):
             self.jitter.push_uint64_t(self.CALL_FINISH_ADDR)
 
         # Set the runtime guard
-        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle)
+        self.jitter.add_breakpoint(
+            self.CALL_FINISH_ADDR,
+            self.__class__.code_sentinelle
+        )
 
     def run(self, addr=None):
         """
@@ -661,14 +695,16 @@ class Sandbox_Linux_arml(Sandbox, Arch_arml, OS_Linux):
         if self.options.mimic_env:
             env_ptrs = []
             for env in self.envp:
-                env += "\x00"
+                env = force_bytes(env)
+                env += b"\x00"
                 self.jitter.cpu.SP -= len(env)
                 ptr = self.jitter.cpu.SP
                 self.jitter.vm.set_mem(ptr, env)
                 env_ptrs.append(ptr)
             argv_ptrs = []
             for arg in self.argv:
-                arg += "\x00"
+                arg = force_bytes(arg)
+                arg += b"\x00"
                 self.jitter.cpu.SP -= len(arg)
                 ptr = self.jitter.cpu.SP
                 self.jitter.vm.set_mem(ptr, arg)
@@ -688,7 +724,10 @@ class Sandbox_Linux_arml(Sandbox, Arch_arml, OS_Linux):
         self.jitter.cpu.LR = self.CALL_FINISH_ADDR
 
         # Set the runtime guard
-        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle)
+        self.jitter.add_breakpoint(
+            self.CALL_FINISH_ADDR,
+            self.__class__.code_sentinelle
+        )
 
     def run(self, addr=None):
         if addr is None and self.options.address is None:
@@ -714,14 +753,16 @@ class Sandbox_Linux_armtl(Sandbox, Arch_armtl, OS_Linux):
         if self.options.mimic_env:
             env_ptrs = []
             for env in self.envp:
-                env += "\x00"
+                env = force_bytes(env)
+                env += b"\x00"
                 self.jitter.cpu.SP -= len(env)
                 ptr = self.jitter.cpu.SP
                 self.jitter.vm.set_mem(ptr, env)
                 env_ptrs.append(ptr)
             argv_ptrs = []
             for arg in self.argv:
-                arg += "\x00"
+                arg = force_bytes(arg)
+                arg += b"\x00"
                 self.jitter.cpu.SP -= len(arg)
                 ptr = self.jitter.cpu.SP
                 self.jitter.vm.set_mem(ptr, arg)
@@ -741,7 +782,10 @@ class Sandbox_Linux_armtl(Sandbox, Arch_armtl, OS_Linux):
         self.jitter.cpu.LR = self.CALL_FINISH_ADDR
 
         # Set the runtime guard
-        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle)
+        self.jitter.add_breakpoint(
+            self.CALL_FINISH_ADDR,
+            self.__class__.code_sentinelle
+        )
 
     def run(self, addr=None):
         if addr is None and self.options.address is None:
@@ -768,14 +812,16 @@ class Sandbox_Linux_mips32b(Sandbox, Arch_mips32b, OS_Linux):
         if self.options.mimic_env:
             env_ptrs = []
             for env in self.envp:
-                env += "\x00"
+                env = force_bytes(env)
+                env += b"\x00"
                 self.jitter.cpu.SP -= len(env)
                 ptr = self.jitter.cpu.SP
                 self.jitter.vm.set_mem(ptr, env)
                 env_ptrs.append(ptr)
             argv_ptrs = []
             for arg in self.argv:
-                arg += "\x00"
+                arg = force_bytes(arg)
+                arg += b"\x00"
                 self.jitter.cpu.SP -= len(arg)
                 ptr = self.jitter.cpu.SP
                 self.jitter.vm.set_mem(ptr, arg)
@@ -792,7 +838,10 @@ class Sandbox_Linux_mips32b(Sandbox, Arch_mips32b, OS_Linux):
         self.jitter.cpu.RA = 0x1337beef
 
         # Set the runtime guard
-        self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle)
+        self.jitter.add_breakpoint(
+            0x1337beef,
+            self.__class__.code_sentinelle
+        )
 
     def run(self, addr=None):
         if addr is None and self.options.address is None:
@@ -850,14 +899,16 @@ class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux):
         if self.options.mimic_env:
             env_ptrs = []
             for env in self.envp:
-                env += "\x00"
+                env = force_bytes(env)
+                env += b"\x00"
                 self.jitter.cpu.SP -= len(env)
                 ptr = self.jitter.cpu.SP
                 self.jitter.vm.set_mem(ptr, env)
                 env_ptrs.append(ptr)
             argv_ptrs = []
             for arg in self.argv:
-                arg += "\x00"
+                arg = force_bytes(arg)
+                arg += b"\x00"
                 self.jitter.cpu.SP -= len(arg)
                 ptr = self.jitter.cpu.SP
                 self.jitter.vm.set_mem(ptr, arg)
@@ -874,7 +925,10 @@ class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux):
         self.jitter.cpu.LR = self.CALL_FINISH_ADDR
 
         # Set the runtime guard
-        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle)
+        self.jitter.add_breakpoint(
+            self.CALL_FINISH_ADDR,
+            self.__class__.code_sentinelle
+        )
 
     def run(self, addr=None):
         if addr is None and self.options.address is None:
@@ -911,14 +965,16 @@ class Sandbox_Linux_ppc32b(Sandbox, Arch_ppc32b, OS_Linux):
         if self.options.mimic_env:
             env_ptrs = []
             for env in self.envp:
-                env += "\x00"
+                env = force_bytes(env)
+                env += b"\x00"
                 self.jitter.cpu.R1 -= len(env)
                 ptr = self.jitter.cpu.R1
                 self.jitter.vm.set_mem(ptr, env)
                 env_ptrs.append(ptr)
             argv_ptrs = []
             for arg in self.argv:
-                arg += "\x00"
+                arg = force_bytes(arg)
+                arg += b"\x00"
                 self.jitter.cpu.R1 -= len(arg)
                 ptr = self.jitter.cpu.R1
                 self.jitter.vm.set_mem(ptr, arg)
@@ -947,8 +1003,10 @@ class Sandbox_Linux_ppc32b(Sandbox, Arch_ppc32b, OS_Linux):
         self.jitter.cpu.LR = self.CALL_FINISH_ADDR
 
         # Set the runtime guard
-        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR,
-                                   self.__class__.code_sentinelle)
+        self.jitter.add_breakpoint(
+            self.CALL_FINISH_ADDR,
+            self.__class__.code_sentinelle
+        )
 
     def run(self, addr=None):
         """
diff --git a/miasm2/analysis/simplifier.py b/miasm2/analysis/simplifier.py
index ca8e74fb..10d5e092 100644
--- a/miasm2/analysis/simplifier.py
+++ b/miasm2/analysis/simplifier.py
@@ -24,7 +24,7 @@ log.setLevel(logging.WARNING)
 def fix_point(func):
     @wraps(func)
     def ret_func(self, ircfg, head):
-        log.debug('[%s]: start', func.func_name)
+        log.debug('[%s]: start', func.__name__)
         has_been_modified = False
         modified = True
         while modified:
@@ -32,7 +32,7 @@ def fix_point(func):
             has_been_modified |= modified
         log.debug(
             '[%s]: stop %r',
-            func.func_name,
+            func.__name__,
             has_been_modified
         )
         return has_been_modified
diff --git a/miasm2/analysis/ssa.py b/miasm2/analysis/ssa.py
index 501cdd5e..54d17dc1 100644
--- a/miasm2/analysis/ssa.py
+++ b/miasm2/analysis/ssa.py
@@ -1,4 +1,5 @@
 from collections import deque
+from future.utils import viewitems, viewvalues
 
 from miasm2.expression.expression import ExprId, ExprAssign, ExprOp, \
     ExprLoc, get_expr_ids
@@ -246,7 +247,7 @@ class SSA(object):
             instructions = []
             # insert SSA instructions
             for _ in assignblk:
-                instructions.append(ssa_iter.next())
+                instructions.append(next(ssa_iter))
             # replace instructions of assignblock in IRBlock
             new_irs.append(AssignBlock(instructions, assignblk.instr))
         return IRBlock(irblock.loc_key, new_irs)
@@ -576,7 +577,7 @@ class SSADiGraph(SSA):
         # if successor is in block's dominance frontier
         if successor in self._phinodes:
             # walk over all variables on LHS
-            for dst, src in self._phinodes[successor].iteritems():
+            for dst, src in list(viewitems(self._phinodes[successor])):
                 # transform variable on RHS in non-SSA form
                 expr = self.reverse_variable(dst)
                 # transform expr into it's SSA form using current stack
@@ -618,7 +619,7 @@ class SSADiGraph(SSA):
         """
         var_to_insert = set()
         for loc_key in self._phinodes:
-            for dst, sources in self._phinodes[loc_key].iteritems():
+            for dst, sources in viewitems(self._phinodes[loc_key]):
                 for src in sources.args:
                     if src in self.ssa_variable_to_expr:
                         continue
@@ -641,14 +642,14 @@ class SSADiGraph(SSA):
 
         # Updt structure
         for loc_key in self._phinodes:
-            for dst, sources in self._phinodes[loc_key].items():
+            for dst, sources in viewitems(self._phinodes[loc_key]):
                 self._phinodes[loc_key][dst] = sources.replace_expr(var_to_newname)
 
-        for var, (loc_key, index) in self.ssa_to_location.items():
+        for var, (loc_key, index) in list(viewitems(self.ssa_to_location)):
             if loc_key == head:
                 self.ssa_to_location[var] = loc_key, index + 1
 
-        for newname, var in newname_to_var.iteritems():
+        for newname, var in viewitems(newname_to_var):
             self.ssa_to_location[newname] = head, 0
             self.ssa_variable_to_expr[newname] = var
             self.expressions[newname] = var
@@ -661,7 +662,7 @@ def irblock_has_phi(irblock):
     """
     if not irblock.assignblks:
         return False
-    for src in irblock[0].itervalues():
+    for src in viewvalues(irblock[0]):
         return src.is_op('Phi')
     return False
 
@@ -765,7 +766,7 @@ class UnSSADiGraph(object):
         """
         ircfg = self.ssa.graph
 
-        for irblock in ircfg.blocks.values():
+        for irblock in list(viewvalues(ircfg.blocks)):
             if not irblock_has_phi(irblock):
                 continue
 
@@ -788,7 +789,7 @@ class UnSSADiGraph(object):
                 for parent, src in self.phi_parent_sources[dst]:
                     parent_to_parallel_copies.setdefault(parent, {})[new_var] = src
 
-            for parent, parallel_copies in parent_to_parallel_copies.iteritems():
+            for parent, parallel_copies in viewitems(parent_to_parallel_copies):
                 parent = ircfg.blocks[parent]
                 assignblks = list(parent)
                 assignblks.append(AssignBlock(parallel_copies, parent[-1].instr))
@@ -810,10 +811,10 @@ class UnSSADiGraph(object):
         node
         """
         ircfg = self.ssa.graph
-        for irblock in ircfg.blocks.itervalues():
+        for irblock in viewvalues(ircfg.blocks):
             if not irblock_has_phi(irblock):
                 continue
-            for dst, sources in irblock[0].iteritems():
+            for dst, sources in viewitems(irblock[0]):
                 assert sources.is_op('Phi')
                 new_var = self.create_copy_var(dst)
                 self.phi_new_var[dst] = new_var
@@ -836,7 +837,7 @@ class UnSSADiGraph(object):
         """
         Generate trivial coalescing of phi variable and itself
         """
-        for phi_new_var in self.phi_new_var.itervalues():
+        for phi_new_var in viewvalues(self.phi_new_var):
             self.merge_state.setdefault(phi_new_var, set([phi_new_var]))
 
     def order_ssa_var_dom(self):
@@ -1009,7 +1010,7 @@ class UnSSADiGraph(object):
         assignments.
         @parent: Optional parent location of the phi source for liveness tests
         """
-        for dst, src in parallel_copies.iteritems():
+        for dst, src in viewitems(parallel_copies):
             dst_merge = self.merge_state.setdefault(dst, set([dst]))
             src_merge = self.merge_state.setdefault(src, set([src]))
             if not self.merge_sets_interfere(dst_merge, src_merge, parent):
@@ -1023,7 +1024,7 @@ class UnSSADiGraph(object):
         ircfg = self.ssa.graph
 
         # Run coalesce on the post phi parallel copy
-        for irblock in ircfg.blocks.values():
+        for irblock in viewvalues(ircfg.blocks):
             if not irblock_has_phi(irblock):
                 continue
             parallel_copies = {}
@@ -1041,7 +1042,7 @@ class UnSSADiGraph(object):
                 for parent, src in self.phi_parent_sources[dst]:
                     parent_to_parallel_copies.setdefault(parent, {})[new_var] = src
 
-            for parent, parallel_copies in parent_to_parallel_copies.iteritems():
+            for parent, parallel_copies in viewitems(parent_to_parallel_copies):
                 self.aggressive_coalesce_parallel_copy(parallel_copies, parent)
 
     def get_best_merge_set_name(self, merge_set):
@@ -1069,7 +1070,7 @@ class UnSSADiGraph(object):
 
         # Elect representative for merge sets
         merge_set_to_name = {}
-        for merge_set in self.merge_state.itervalues():
+        for merge_set in viewvalues(self.merge_state):
             frozen_merge_set = frozenset(merge_set)
             merge_sets.add(frozen_merge_set)
             var_name = self.get_best_merge_set_name(merge_set)
@@ -1090,10 +1091,10 @@ class UnSSADiGraph(object):
         @ircfg: IRDiGraph instance
         """
 
-        for irblock in self.ssa.graph.blocks.values():
+        for irblock in list(viewvalues(self.ssa.graph.blocks)):
             assignblks = list(irblock)
             out = {}
-            for dst, src in assignblks[0].iteritems():
+            for dst, src in viewitems(assignblks[0]):
                 if src.is_op('Phi'):
                     assert set([dst]) == set(src.args)
                     continue
@@ -1105,11 +1106,11 @@ class UnSSADiGraph(object):
         """
         Remove trivial expressions (a=a) in the current graph
         """
-        for irblock in self.ssa.graph.blocks.values():
+        for irblock in list(viewvalues(self.ssa.graph.blocks)):
             assignblks = list(irblock)
             for i, assignblk in enumerate(assignblks):
                 out = {}
-                for dst, src in assignblk.iteritems():
+                for dst, src in viewitems(assignblk):
                     if dst == src:
                         continue
                     out[dst] = src