예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
    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()
예제 #4
0
    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()
예제 #5
0
    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])
예제 #6
0
    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])
예제 #7
0
    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)
예제 #8
0
    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)
예제 #9
0
    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)
예제 #10
0
    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()