'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.'

def _track(self, state, live_defs):

    live_defs = live_defs.copy()
    action_list = list(state.history.recent_actions)
    temps = {}
    temps_to_edges = defaultdict(list)
    regs_to_edges = defaultdict(list)
    def _annotate_edges_in_dict(dict_, key, **new_labels):
        '\n\n                                                :param    dict_:                            The    dict,    can    be    either    `temps_to_edges`    or    `regs_to_edges`\n                                                :param    key:                                    The    key    used    in    finding    elements    in    the    dict\n                                                :param    new_labels:        New    labels    to    be    added    to    those    edges\n                                                '
        for edge_tuple in dict_[key]:
            (_, _, labels) = edge_tuple
            for (k, v) in new_labels.iteritems():
                if (k in labels):
                    labels[k] = (labels[k] + (v,))
                else:
                    labels[k] = (v,)
    def _dump_edge_from_dict(dict_, key, del_key=True):
        '\n                                                Pick    an    edge    from    the    dict    based    on    the    key    specified,    add    it    to    our    graph,    and    remove    the    key    from    dict.\n\n                                                :param    dict_:            The    dict,    can    be    either    `temps_to_edges`    or    `regs_to_edges`.\n                                                :param    key:                    The    key    used    in    finding    elements    in    the    dict.\n                                                '
        for edge_tuple in dict_[key]:
            (prev_code_loc, current_code_loc, labels) = edge_tuple
            self._add_edge(prev_code_loc, current_code_loc, **labels)
        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):
                addr_list = set(state.memory.normalize_address(a.addr.ast, convert_to_valueset=True))
            else:
                addr_list = set(a.actual_addrs)
            for addr in addr_list:
                variable = SimMemoryVariable(addr, a.data.ast.size())
                if (a.action == 'read'):
                    prevdefs = self._def_lookup(live_defs, variable)
                    for (prev_code_loc, labels) in prevdefs.iteritems():
                        self._read_edge = True
                        self._add_edge(prev_code_loc, current_code_loc, **labels)
                else:
                    self._kill(live_defs, variable, current_code_loc)
                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'):
            variable = SimRegisterVariable(a.offset, self.project.arch.bits)
            if (a.action == 'read'):
                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.iteritems():
                    edge_tuple = (prev_code_loc, current_code_loc, labels)
                    regs_to_edges[a.offset].append(edge_tuple)
            else:
                self._kill(live_defs, variable, current_code_loc)
        elif (a.type == 'tmp'):
            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:
                temps[a.tmp] = current_code_loc
        elif (a.type == 'exit'):
            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)
    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
