def process(self): logger.debug('METHOD : %s', self.name) # Native methods... no blocks. if self.start_block is None: logger.debug('Native Method.') self.writer = Writer(None, self) self.writer.write_method() return graph = construct(self.start_block, self.var_to_name, self.exceptions) self.graph = graph if not __debug__: util.create_png(self.cls_name, self.name, graph, '/tmp/dad/blocks') use_defs, def_uses = build_def_use(graph, self.lparams) split_variables(graph, self.var_to_name, def_uses, use_defs) # TODO: split_variables should update DU/UD use_defs, def_uses = build_def_use(graph, self.lparams) dead_code_elimination(graph, def_uses, use_defs) register_propagation(graph, def_uses, use_defs) place_declarations(graph, self.var_to_name, def_uses, use_defs) del def_uses, use_defs # After the DCE pass, some nodes may be empty, so we can simplify the # graph to delete these nodes. # We start by restructuring the graph by spliting the conditional nodes # into a pre-header and a header part. graph.split_if_nodes() # We then simplify the graph by merging multiple statement nodes into # a single statement node when possible. This also delete empty nodes. graph.simplify() graph.compute_rpo() if not __debug__: util.create_png(self.cls_name, self.name, graph, '/tmp/dad/pre-structured') identify_structures(graph, graph.immediate_dominators()) if not __debug__: util.create_png(self.cls_name, self.name, graph, '/tmp/dad/structured') self.writer = Writer(graph, self) self.writer.write_method() del graph
def process(self, doAST=False): logger.debug('METHOD : %s', self.name) # Native methods... no blocks. if self.start_block is None: logger.debug('Native Method.') if doAST: self.ast = JSONWriter(None, self).get_ast() else: self.writer = Writer(None, self) self.writer.write_method() return # Construct the CFG graph = construct(self.start_block, self.var_to_name, self.exceptions) self.graph = graph if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/blocks') use_defs, def_uses = build_def_use(graph, self.lparams) split_variables(graph, self.var_to_name, def_uses, use_defs) dead_code_elimination(graph, def_uses, use_defs) register_propagation(graph, def_uses, use_defs) # FIXME var_to_name need to contain the created tmp variables. # This seems to be a workaround, we add them into the list manually for var, i in def_uses: if not isinstance(var, int): self.var_to_name[var] = var.upper() place_declarations(graph, self.var_to_name, def_uses, use_defs) del def_uses, use_defs # After the DCE pass, some nodes may be empty, so we can simplify the # graph to delete these nodes. # We start by restructuring the graph by spliting the conditional nodes # into a pre-header and a header part. split_if_nodes(graph) # We then simplify the graph by merging multiple statement nodes into # a single statement node when possible. This also delete empty nodes. simplify(graph) graph.compute_rpo() if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/pre-structured') identify_structures(graph, graph.immediate_dominators()) if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/structured') if doAST: self.ast = JSONWriter(graph, self).get_ast() else: self.writer = Writer(graph, self) self.writer.write_method()
def testDefUseGCD(self, mock_reach_def): """Test def use with the GCD function above.""" n1 = self._CreateMockNode('n1', 0, [(['a'], 'c'), (['b'], 'd')]) n2 = self._CreateMockNode('n2', 2, [(['c'], None)]) n3 = self._CreateMockNode('n3', 3, [(['d'], 'ret')]) n4 = self._CreateMockNode('n4', 4, [(['d'], None)]) n5 = self._CreateMockNode('n5', 5, [(['c', 'd'], None)]) n6 = self._CreateMockNode('n6', 6, [(['c', 'd'], 'c')]) n7 = self._CreateMockNode('n7', 7, [(['c', 'd'], 'd')]) n8 = self._CreateMockNode('n8', 8, [(['c'], 'ret')]) n9 = self._CreateMockNode('n9', 9, [(['ret'], None)]) graph_mock = mock.create_autospec(graph.Graph) graph_mock.rpo = [n1, n2, n3, n4, n5, n6, n7, n8, n9] mock_analysis = mock_reach_def.return_value mock_analysis.def_to_loc = {'a': set([-1]), 'b': set([-2]), 'c': set([0, 6]), 'd': set([1, 7]), 'ret': set([3, 8])} mock_analysis.defs = {n1: {'c': set([0]), 'd': set([1])}, n2: {}, n3: {'ret': set([3])}, n4: {}, n5: {}, n6: {'c': set([6])}, n7: {'d': set([7])}, n8: {'ret': set([8])}, n9: {}} mock_analysis.R = {n1: set([-2, -1]), n2: set([-2, -1, 0, 1]), n3: set([-2, -1, 0, 1]), n4: set([-2, -1, 0, 1]), n5: set([-2, -1, 0, 1]), n6: set([-2, -1, 0, 1]), n7: set([-2, -1, 0, 1]), n8: set([-2, -1, 0, 1, 6, 7]), n9: set([-2, -1, 0, 1, 3, 6, 7, 8])} expected_du = {('a', -1): [0], ('b', -2): [1], ('c', 0): [2, 5, 6, 7, 8], ('c', 6): [8], ('d', 1): [3, 4, 5, 6, 7], ('ret', 3): [9], ('ret', 8): [9]} expected_ud = {('a', 0): [-1], ('b', 1): [-2], ('c', 2): [0], ('c', 5): [0], ('c', 6): [0], ('c', 7): [0], ('c', 8): [0, 6], ('d', 3): [1], ('d', 4): [1], ('d', 5): [1], ('d', 6): [1], ('d', 7): [1], ('ret', 9): [3, 8]} ud, du = dataflow.build_def_use(graph_mock, mock.sentinel) self.assertItemsEqual(du, expected_du) for entry in du: self.assertItemsEqual(du[entry], expected_du[entry]) self.assertItemsEqual(ud, expected_ud) for entry in ud: self.assertItemsEqual(ud[entry], expected_ud[entry])
def testDefUseIfBool(self, mock_reach_def): n1 = self._CreateMockNode('n1', 0, [([], 0), ([2], None)]) n2 = self._CreateMockNode('n1', 2, [([3], None)]) n3 = self._CreateMockNode('n3', 3, [([3], None)]) n4 = self._CreateMockNode('n4', 4, [([], 0)]) n5 = self._CreateMockNode('n5', 5, [([0], 0)]) n6 = self._CreateMockNode('n6', 6, [([2], 1), ([0, 1], 0)]) n7 = self._CreateMockNode('n7', 8, [([0], None)]) graph_mock = mock.create_autospec(graph.Graph) graph_mock.rpo = [n1, n2, n3, n4, n5, n6, n7] mock_analysis = mock_reach_def.return_value mock_analysis.def_to_loc = {0: set([0, 4, 5, 7]), 1: set([6]), 2: set([-1]), 3: set([-2])} mock_analysis.defs = {n1: {0: set([0])}, n2: {}, n3: {}, n4: {0: set([4])}, n5: {0: set([5])}, n6: {0: set([7]), 1: set([6])}, n7: {}} mock_analysis.R = {n1: set([-1, -2]), n2: set([0, -2, -1]), n3: set([0, -1, -2]), n4: set([0, -2, -1]), n5: set([0, -2, -1]), n6: set([0, -1, -2]), n7: set([4, -1, 6, 7, -2, 5])} expected_du = {(0, 0): [7, 5], (0, 4): [8], (0, 5): [8], (0, 7): [8], (1, 6): [7], (2, -1): [6, 1], (3, -2): [2, 3]} expected_ud = {(0, 5): [0], (0, 7): [0], (0, 8): [4, 5, 7], (1, 7): [6], (2, 1): [-1], (2, 6): [-1], (3, 2): [-2], (3, 3): [-2]} ud, du = dataflow.build_def_use(graph_mock, mock.sentinel) self.assertEqual(du, expected_du) self.assertEqual(ud, expected_ud)
def testDefUseIfBool(self, mock_reach_def): n1 = self._CreateMockNode('n1', 0, [([], 0), ([2], None)]) n2 = self._CreateMockNode('n1', 2, [([3], None)]) n3 = self._CreateMockNode('n3', 3, [([3], None)]) n4 = self._CreateMockNode('n4', 4, [([], 0)]) n5 = self._CreateMockNode('n5', 5, [([0], 0)]) n6 = self._CreateMockNode('n6', 6, [([2], 1), ([0, 1], 0)]) n7 = self._CreateMockNode('n7', 8, [([0], None)]) graph_mock = mock.create_autospec(graph.Graph) graph_mock.rpo = [n1, n2, n3, n4, n5, n6, n7] mock_analysis = mock_reach_def.return_value mock_analysis.def_to_loc = { 0: set([0, 4, 5, 7]), 1: set([6]), 2: set([-1]), 3: set([-2]) } mock_analysis.defs = { n1: {0: set([0])}, n2: {}, n3: {}, n4: {0: set([4])}, n5: {0: set([5])}, n6: {0: set([7]), 1: set([6])}, n7: {} } mock_analysis.R = { n1: set([-1, -2]), n2: set([0, -2, -1]), n3: set([0, -1, -2]), n4: set([0, -2, -1]), n5: set([0, -2, -1]), n6: set([0, -1, -2]), n7: set([4, -1, 6, 7, -2, 5]) } expected_du = { (0, 0): [7, 5], (0, 4): [8], (0, 5): [8], (0, 7): [8], (1, 6): [7], (2, -1): [6, 1], (3, -2): [2, 3] } expected_ud = { (0, 5): [0], (0, 7): [0], (0, 8): [4, 5, 7], (1, 7): [6], (2, 1): [-1], (2, 6): [-1], (3, 2): [-2], (3, 3): [-2] } ud, du = dataflow.build_def_use(graph_mock, mock.sentinel) self.assertEqual(ud, expected_ud) # FIXME the test will fail for python3 here, because DU # is build up from the dict UD. # But as sets are unordered, the resulting lists in DU # are unordered as well. # For some reason the python2 variant is very consistent # while py3 iterates over the set differently. # I'm not sure if the order is important... # Maybe need to change the test here or fix the code #(e.g. use defaultdict(set) instead of defaultdict(list) self.assertEqual(du, expected_du)
def process(self, doAST=False): """ Processes the method and decompile the code. There are two modes of operation: 1) Normal Decompilation to Java Code 2) Decompilation into an abstract syntax tree (AST) The Decompilation is done twice. First, a rough decompilation is created, which is then optimized. Second, the optimized version is used to create the final version. :param doAST: generate AST instead of Java Code """ logger.debug('METHOD : %s', self.name) # Native methods... no blocks. if self.start_block is None: logger.debug('Native Method.') if doAST: self.ast = JSONWriter(None, self).get_ast() else: self.writer = Writer(None, self) self.writer.write_method() return # Construct the CFG graph = construct(self.start_block, self.var_to_name, self.exceptions) self.graph = graph if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/blocks') use_defs, def_uses = build_def_use(graph, self.lparams) split_variables(graph, self.var_to_name, def_uses, use_defs) dead_code_elimination(graph, def_uses, use_defs) register_propagation(graph, def_uses, use_defs) resolve_variables_type(graph, self.var_to_name, def_uses, use_defs) new_instance_propgation(graph, def_uses, use_defs) #for dummy setattr(graph, "group_var", group_variables(self.var_to_name, def_uses, use_defs)) # FIXME var_to_name need to contain the created tmp variables. # This seems to be a workaround, we add them into the list manually for var, i in def_uses: if not isinstance(var, int): self.var_to_name[var] = var.upper() place_declarations(graph, self.var_to_name, def_uses, use_defs) del def_uses, use_defs # After the DCE pass, some nodes may be empty, so we can simplify the # graph to delete these nodes. # We start by restructuring the graph by spliting the conditional nodes # into a pre-header and a header part. split_if_nodes(graph) # We then simplify the graph by merging multiple statement nodes into # a single statement node when possible. This also delete empty nodes. simplify(graph) graph.compute_rpo() if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/pre-structured') identify_structures(graph, graph.immediate_dominators()) if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/structured') if doAST: self.ast = JSONWriter(graph, self).get_ast() else: self.writer = Writer(graph, self) self.writer.write_method()