(self, state, live_defs)
return live_defs
Given all live definitions prior to this program point, track the changes, and return a new list of live
        definitions. We scan through the action list of the new state to track the changes.

        :param state:       The input state at that program point.
        :param live_defs:   A list of all live definitions prior to reaching this program point.
        :returns:           A list of new live definitions.
Given all live definitions prior to this program point, track the changes, and return a new list of live
        definitions. We scan through the action list of the new state to track the changes.
Given all live definitions prior to this program point track the changes and return a new list of live definitions . We scan through the action list of the new state to track the changes .
def _track(self, state, live_defs):
        """
        Given all live definitions prior to this program point, track the changes, and return a new list of live
        definitions. We scan through the action list of the new state to track the changes.

        :param state:       The input state at that program point.
        :param live_defs:   A list of all live definitions prior to reaching this program point.
        :returns:           A list of new live definitions.
        """

        # Make a copy of live_defs
        live_defs = live_defs.copy()

        action_list = list(state.history.recent_actions)

        # Since all temporary variables are local, we simply track them in a local dict
        temps = { }

        # All dependence edges are added to the graph either at the end of this method, or when they are going to be
        # overwritten by a new edge. This is because we sometimes have to modify a  previous edge (e.g. add new labels
        # to the edge)
        temps_to_edges = defaultdict(list)
        regs_to_edges = defaultdict(list)

        def _annotate_edges_in_dict(dict_, key, **new_labels):
            """

            :param dict_:       The dict, can be either `temps_to_edges` or `regs_to_edges`
            :param key:         The key used in finding elements in the dict
            :param new_labels:  New labels to be added to those edges
            """

            for edge_tuple in dict_[key]:
                # unpack it
                _, _, labels = edge_tuple
                for k, v in new_labels.items():
                    if k in labels:
                        labels[k] = labels[k] + (v, )
                    else:
                        # Construct a tuple
                        labels[k] = (v, )

        def _dump_edge_from_dict(dict_, key, del_key=True):
            """
            Pick an edge from the dict based on the key specified, add it to our graph, and remove the key from dict.

            :param dict_:   The dict, can be either `temps_to_edges` or `regs_to_edges`.
            :param key:     The key used in finding elements in the dict.
            """
            for edge_tuple in dict_[key]:
                # unpack it
                prev_code_loc, current_code_loc, labels = edge_tuple
                # Add the new edge
                self._add_edge(prev_code_loc, current_code_loc, **labels)

            # Clear it
            if del_key:
                del dict_[key]

        for a in action_list:

            if a.bbl_addr is None:
                current_code_loc = CodeLocation(None, None, sim_procedure=a.sim_procedure)
            else:
                current_code_loc = CodeLocation(a.bbl_addr, a.stmt_idx, ins_addr=a.ins_addr)

            if a.type == "mem":
                if a.actual_addrs is None:
                    # For now, mem reads don't necessarily have actual_addrs set properly
                    addr_list = set(aw.to_valueset(state) for aw in state.memory._concretize_address_descriptor(a.addr.ast))
                else:
                    addr_list = set(a.actual_addrs)

                for addr in addr_list:
                    variable = SimMemoryVariable(addr, a.data.ast.size()) # TODO: Properly unpack the SAO

                    if a.action == "read":
                        # Create an edge between def site and use site

                        prevdefs = self._def_lookup(live_defs, variable)

                        for prev_code_loc, labels in prevdefs.items():
                            self._read_edge = True
                            self._add_edge(prev_code_loc, current_code_loc, **labels)

                    else: #if a.action == "write":
                        # Kill the existing live def
                        self._kill(live_defs, variable, current_code_loc)

                    # For each of its register dependency and data dependency, we revise the corresponding edge
                    for reg_off in a.addr.reg_deps:
                        _annotate_edges_in_dict(regs_to_edges, reg_off, subtype='mem_addr')
                    for tmp in a.addr.tmp_deps:
                        _annotate_edges_in_dict(temps_to_edges, tmp, subtype='mem_addr')

                    for reg_off in a.data.reg_deps:
                        _annotate_edges_in_dict(regs_to_edges, reg_off, subtype='mem_data')
                    for tmp in a.data.tmp_deps:
                        _annotate_edges_in_dict(temps_to_edges, tmp, subtype='mem_data')

            elif a.type == 'reg':
                # For now, we assume a.offset is not symbolic
                # TODO: Support symbolic register offsets

                #variable = SimRegisterVariable(a.offset, a.data.ast.size())
                variable = SimRegisterVariable(a.offset, self.project.arch.bits)

                if a.action == 'read':
                    # What do we want to do?
                    prevdefs = self._def_lookup(live_defs, variable)

                    if a.offset in regs_to_edges:
                        _dump_edge_from_dict(regs_to_edges, a.offset)

                    for prev_code_loc, labels in prevdefs.items():
                        edge_tuple = (prev_code_loc, current_code_loc, labels)
                        regs_to_edges[a.offset].append(edge_tuple)

                else:
                    # write
                    self._kill(live_defs, variable, current_code_loc)

            elif a.type == 'tmp':
                # tmp is definitely not symbolic
                if a.action == 'read':
                    prev_code_loc = temps[a.tmp]
                    edge_tuple = (prev_code_loc, current_code_loc, {'type':'tmp', 'data':a.tmp})

                    if a.tmp in temps_to_edges:
                        _dump_edge_from_dict(temps_to_edges, a.tmp)

                    temps_to_edges[a.tmp].append(edge_tuple)

                else:
                    # write
                    temps[a.tmp] = current_code_loc

            elif a.type == 'exit':
                # exits should only depend on tmps

                for tmp in a.tmp_deps:
                    prev_code_loc = temps[tmp]
                    edge_tuple = (prev_code_loc, current_code_loc, {'type': 'exit', 'data': tmp})

                    if tmp in temps_to_edges:
                        _dump_edge_from_dict(temps_to_edges, tmp)

                    temps_to_edges[tmp].append(edge_tuple)

        # In the end, dump all other edges in those two dicts
        for reg_offset in regs_to_edges:
            _dump_edge_from_dict(regs_to_edges, reg_offset, del_key=False)
        for tmp in temps_to_edges:
            _dump_edge_from_dict(temps_to_edges, tmp, del_key=False)

        return live_defs
def _track ( self , state , live_defs ) : # Make a copy of live_defs live_defs = live_defs . copy ( ) action_list = list ( state . history . recent_actions ) # Since all temporary variables are local, we simply track them in a local dict temps = { } # All dependence edges are added to the graph either at the end of this method, or when they are going to be # overwritten by a new edge. This is because we sometimes have to modify a  previous edge (e.g. add new labels # to the edge) temps_to_edges = defaultdict ( list ) regs_to_edges = defaultdict ( list ) def _annotate_edges_in_dict ( dict_ , key , * * new_labels ) : """

            :param dict_:       The dict, can be either `temps_to_edges` or `regs_to_edges`
            :param key:         The key used in finding elements in the dict
            :param new_labels:  New labels to be added to those edges
            """ for edge_tuple in dict_ [ key ] : # unpack it _ , _ , labels = edge_tuple for k , v in new_labels . items ( ) : if k in labels : labels [ k ] = labels [ k ] + ( v , ) else : # Construct a tuple labels [ k ] = ( v , ) def _dump_edge_from_dict ( dict_ , key , del_key = True ) : """
            Pick an edge from the dict based on the key specified, add it to our graph, and remove the key from dict.

            :param dict_:   The dict, can be either `temps_to_edges` or `regs_to_edges`.
            :param key:     The key used in finding elements in the dict.
            """ for edge_tuple in dict_ [ key ] : # unpack it prev_code_loc , current_code_loc , labels = edge_tuple # Add the new edge self . _add_edge ( prev_code_loc , current_code_loc , * * labels ) # Clear it if del_key : del dict_ [ key ] for a in action_list : if a . bbl_addr is None : current_code_loc = CodeLocation ( None , None , sim_procedure = a . sim_procedure ) else : current_code_loc = CodeLocation ( a . bbl_addr , a . stmt_idx , ins_addr = a . ins_addr ) if a . type == "mem" : if a . actual_addrs is None : # For now, mem reads don't necessarily have actual_addrs set properly addr_list = set ( aw . to_valueset ( state ) for aw in state . memory . _concretize_address_descriptor ( a . addr . ast ) ) else : addr_list = set ( a . actual_addrs ) for addr in addr_list : variable = SimMemoryVariable ( addr , a . data . ast . size ( ) ) # TODO: Properly unpack the SAO if a . action == "read" : # Create an edge between def site and use site prevdefs = self . _def_lookup ( live_defs , variable ) for prev_code_loc , labels in prevdefs . items ( ) : self . _read_edge = True self . _add_edge ( prev_code_loc , current_code_loc , * * labels ) else : #if a.action == "write": # Kill the existing live def self . _kill ( live_defs , variable , current_code_loc ) # For each of its register dependency and data dependency, we revise the corresponding edge for reg_off in a . addr . reg_deps : _annotate_edges_in_dict ( regs_to_edges , reg_off , subtype = 'mem_addr' ) for tmp in a . addr . tmp_deps : _annotate_edges_in_dict ( temps_to_edges , tmp , subtype = 'mem_addr' ) for reg_off in a . data . reg_deps : _annotate_edges_in_dict ( regs_to_edges , reg_off , subtype = 'mem_data' ) for tmp in a . data . tmp_deps : _annotate_edges_in_dict ( temps_to_edges , tmp , subtype = 'mem_data' ) elif a . type == 'reg' : # For now, we assume a.offset is not symbolic # TODO: Support symbolic register offsets #variable = SimRegisterVariable(a.offset, a.data.ast.size()) variable = SimRegisterVariable ( a . offset , self . project . arch . bits ) if a . action == 'read' : # What do we want to do? prevdefs = self . _def_lookup ( live_defs , variable ) if a . offset in regs_to_edges : _dump_edge_from_dict ( regs_to_edges , a . offset ) for prev_code_loc , labels in prevdefs . items ( ) : edge_tuple = ( prev_code_loc , current_code_loc , labels ) regs_to_edges [ a . offset ] . append ( edge_tuple ) else : # write self . _kill ( live_defs , variable , current_code_loc ) elif a . type == 'tmp' : # tmp is definitely not symbolic if a . action == 'read' : prev_code_loc = temps [ a . tmp ] edge_tuple = ( prev_code_loc , current_code_loc , { 'type' : 'tmp' , 'data' : a . tmp } ) if a . tmp in temps_to_edges : _dump_edge_from_dict ( temps_to_edges , a . tmp ) temps_to_edges [ a . tmp ] . append ( edge_tuple ) else : # write temps [ a . tmp ] = current_code_loc elif a . type == 'exit' : # exits should only depend on tmps for tmp in a . tmp_deps : prev_code_loc = temps [ tmp ] edge_tuple = ( prev_code_loc , current_code_loc , { 'type' : 'exit' , 'data' : tmp } ) if tmp in temps_to_edges : _dump_edge_from_dict ( temps_to_edges , tmp ) temps_to_edges [ tmp ] . append ( edge_tuple ) # In the end, dump all other edges in those two dicts for reg_offset in regs_to_edges : _dump_edge_from_dict ( regs_to_edges , reg_offset , del_key = False ) for tmp in temps_to_edges : _dump_edge_from_dict ( temps_to_edges , tmp , del_key = False ) return live_defs