Пример #1
0
    def add_node(self, node, show_exit):

        try:
            not show_exit and BB_EXIT in node.bb.flags
        except:
            from trepan.api import debug

            debug()
        if not show_exit and BB_EXIT in node.bb.flags:
            return

        label = ""
        style = ""
        align = "\l"

        is_exit = False
        if BB_ENTRY in node.bb.flags:
            style = '[shape = "oval"]'
        elif BB_EXIT in node.bb.flags:
            style = '[shape = "diamond"]'
            align = "\n"
            is_exit = True
        elif not node.bb.predecessors:
            style = '[style = "dashed"]'
            pass
        label = '[label="Basic Block %d%s%s%s"]' % (
            node.number,
            align,
            self.node_repr(node.bb, align, is_exit),
            align,
        )
        self.buffer += "  block_%d %s%s;\n" % (node.number, style, label)
Пример #2
0
def deparse_offset(co, name, last_i, errmsg_fn):
    nodeInfo = None
    deparsed = deparse_cache.get(co, None)
    if not deparsed:
        out = StringIO()
        try:
            # FIXME: cache co
            deparsed = code_deparse(co, out)
            from trepan.api import debug
            debug()
        except:
            print(sys.exc_info()[1])
            if errmsg_fn:
                errmsg_fn(sys.exc_info()[1])
                errmsg_fn("error in deparsing code")
        deparse_cache[co] = deparsed
    try:
        nodeInfo = deparsed_find((name, last_i), deparsed, co)
    except:
        if errmsg_fn:
            errmsg_fn(sys.exc_info()[1])
            errmsg_fn("error in deparsing code at offset %d" % last_i)

    if not nodeInfo:
        nodeInfo = deparsed_find((name, last_i), deparsed, co)
    return deparsed, nodeInfo
Пример #3
0
    def run_code(self, code, f_globals=None, f_locals=None, toplevel=True):
        """run code using f_globals and f_locals in our VM"""
        frame = self.make_frame(code, f_globals=f_globals, f_locals=f_locals)
        try:
            val = self.eval_frame(frame)
        except Exception:
            # Until we get test/vmtest.py under control:
            if self.vmtest_testing:
                raise
            if self.last_traceback:
                self.last_traceback.print_tb()
                print("%s" % self.last_exception[0].__name__, end="")
                le1 = self.last_exception[1]
                tail = ""
                if le1:
                    if hasattr(le1, "args"):
                        tail = "\n".join(le1.args)
                    else:
                        from trepan.api import debug
                        debug()
                print(tail)
            raise

        # Frame ran to normal completion... check some invariants
        if toplevel:
            if self.frames:  # pragma: no cover
                raise PyVMError("Frames left over!")
            if self.frame and self.frame.stack:  # pragma: no cover
                raise PyVMError("Data left on stack! %r" % self.frame.stack)

        return val
Пример #4
0
    def run(self):

        itemq = self.itemq
        i = 0
        for j in range(10):
            debug()
            print currentThread(), "Produced One Item:", i
            itemq.put(i, 1)
            i += 1
            time.sleep(1)
            pass
        return
Пример #5
0
    def run(self):

        itemq=self.itemq
        i=0
        for j in range(10):
            debug()
            print(currentThread(), "Produced One Item:", i)
            itemq.put(i, 1)
            i+=1
            time.sleep(1)
            pass
        return
Пример #6
0
 def catch_debug(sig, frame):
     _logger.info('got signal={0} to go into debugger mode'.format(sig))
     from trepan.interfaces import server
     from trepan.api import debug
     try:
         portNum = harvester_config.master.debugger_port
     except Exception:
         portNum = 19550
     connection_opts = {'IO': 'TCP', 'PORT': portNum}
     interface = server.ServerInterface(connection_opts=connection_opts)
     dbg_opts = {'interface': interface}
     _logger.info('starting debugger on port {0}'.format(portNum))
     debug(dbg_opts=dbg_opts)
Пример #7
0
 def catch_debug(sig, frame):
     _logger.info('got signal={0} to go into debugger mode'.format(sig))
     from trepan.interfaces import server
     from trepan.api import debug
     try:
         portNum = harvester_config.master.debugger_port
     except Exception:
         portNum = 19550
     connection_opts = {'IO': 'TCP', 'PORT': portNum}
     interface = server.ServerInterface(connection_opts=connection_opts)
     dbg_opts = {'interface': interface}
     _logger.info('starting debugger on port {0}'.format(portNum))
     debug(dbg_opts=dbg_opts)
Пример #8
0
def gcd(a, b):
    """ GCD. We assume positive numbers"""

    # Make: a <= b
    if a > b:
        (a, b) = (b, a)

    if a <= 0:
        debug(step_ignore=0)
        return None
    if a == 1 or b - a == 0:
        debug(start_opts={'startup-profile': True})
        return a
    return gcd(b - a, a)
Пример #9
0
 def n_c_except_suite(node):
     node_len = len(node)
     if not (node_len == 1 and node[0] in ("except_suite", "c_returns")):
         try:
             node[1]
         except:
             from trepan.api import debug
             debug()
     if node_len == 1 and node[0] in ("except_suite", "c_returns"):
         node = node[0]
         self.default(node)
     elif node[1] in ("c_suite_stmts", "c_except_suite"):
         node = node[1][0]
         template = ("%+%c%-", 0)
         self.template_engine(template, node)
         self.prune()
Пример #10
0
 def wrapped(*args, **kwargs):
     from trepan.api import debug
     debug()
     coro = func(*args, **kwargs)
     if (coro.__class__ is CoroutineType or coro.__class__ is GeneratorType
             and coro.gi_code.co_flags & 0x100):
         # 'coro' is a native coroutine object or an iterable coroutine
         return coro
     if (isinstance(coro, _collections_abc.Generator)
             and not isinstance(coro, _collections_abc.Coroutine)):
         # 'coro' is either a pure Python generator iterator, or it
         # implements collections.abc.Generator (and does not implement
         # collections.abc.Coroutine).
         return _GeneratorWrapper(coro)
     # 'coro' is either an instance of collections.abc.Coroutine or
     # some other object -- pass it through.
     return coro
Пример #11
0
def print_tb(tb, limit=None, file=None, verbosity=0):
    """Print up to 'limit' stack trace entries from the traceback 'tb'.

    If 'limit' is omitted or None, all entries are printed.  If 'file'
    is omitted or None, the output goes to sys.stderr; otherwise
    'file' should be an open file or file-like object with a write()
    method.
    """
    if file is None:
        file = sys.stderr
    if limit is None:
        if hasattr(sys, 'tracebacklimit'):
            limit = sys.tracebacklimit
    n = 0
    nodeInfo = None
    while tb is not None and (limit is None or n < limit):
        f = tb.tb_frame
        lineno = tb.tb_lineno
        co = f.f_code
        filename = co.co_filename
        name = co.co_name

        linecache.checkcache(filename)
        _print(file,
               '  File "%s", line %d, in %s' % (filename, lineno, name))

        if verbosity > 0:
            try:
               deparsed = deparse_code(SYS_VERSION, co)
               from trepan.api import debug; debug()
               nodeInfo = deparsed_find((name, f.f_lasti), deparsed, co)
            except:
                pass

            if nodeInfo:
                extractInfo = deparsed.extract_node_info(nodeInfo)
                _print(file, extractInfo.selectedLine)
                _print(file, extractInfo.markerLine)

            if verbosity > 1:
                _print(file, "instruction: %s" % (nodeInfo.node))

        line = linecache.getline(filename, lineno, f.f_globals)
        if line: _print(file, '    ' + line.strip())
        tb = tb.tb_next
        n = n+1
Пример #12
0
    def get_constant(self, precision, evaluation, preference="mpmath"):
        try:
            d = get_precision(precision, evaluation)
        except PrecisionValueError:
            return

        mpmath_name = self.mpmath_name
        if d is None:
            return MachineReal(mp_fn(mpmath_name))
        elif preference == "mpmath":
            result = mp_fn(mpmath_name, d)
        else:
            sympy_fn = self.to_sympy()
            try:
                result = sympy_fn.n(d)
            except:
                from trepan.api import debug; debug()
                pass
        return PrecisionReal(result)
Пример #13
0
    def __init__(self,
                 host=CELERY_TREPAN_HOST,
                 port=CELERY_TREPAN_PORT,
                 out=sys.stdout):
        self.active = True
        self.out = out

        self.ident = '{0}:{1}'.format(self.me, port)

        from trepan.interfaces import server as Mserver
        connection_opts = {'IO': 'TCP', 'PORT': port}
        self.intf = Mserver.ServerInterface(connection_opts=connection_opts)
        host = self.intf.inout.HOST
        self.host = host if host else '<hostname>'
        from trepan.api import debug
        debug()
        self.port = self.intf.inout.PORT
        self.dbg_opts = {'interface': self.intf}
        return
Пример #14
0
    def write(self, *data):
        from trepan.api import debug
        debug()
        if (len(data) == 1) and data[0] == self.indent:
            diff = max(self.pending_newlines,
                       self.desired_line_number - self.current_line_number)
            self.f.write('\n' * diff)
            self.current_line_number += diff
            self.pending_newlines = 0
        if (len(data) == 0) or (len(data) == 1 and data[0] == ''):
            return

        out = ''.join((str(j) for j in data))
        n = 0
        for i in out:
            if i == '\n':
                n += 1
                if n == len(out):
                    self.pending_newlines = max(self.pending_newlines, n)
                    return
            elif n:
                self.pending_newlines = max(self.pending_newlines, n)
                out = out[n:]
                break
            else:
                break

        if self.pending_newlines > 0:
            diff = max(self.pending_newlines,
                       self.desired_line_number - self.current_line_number)
            self.f.write('\n' * diff)
            self.current_line_number += diff
            self.pending_newlines = 0

        for i in out[::-1]:
            if i == '\n':
                self.pending_newlines += 1
            else:
                break

        if self.pending_newlines:
            out = out[:-self.pending_newlines]
        self.f.write(out)
Пример #15
0
    def test_one(xdis_args, dis_args, has_arg):
        effect = xstack_effect(*xdis_args)
        try:
            check_effect = dis.stack_effect(*dis_args)
        except:
            from trepan.api import debug
            debug()
        assert effect != -100, (
            "%d (%s) needs adjusting; should be: should have effect %d" %
            (opcode, opname, check_effect))
        if has_arg:
            op_val = "with operand %d" % dis_args[1]
        else:
            op_val = ""

        assert check_effect == effect, (
            "%d (%s) %s not okay; effect %d vs %d" %
            (opcode, opname, op_val, effect, check_effect))
        print("%d (%s) is good: effect %d" % (opcode, opname, effect))
Пример #16
0
    def write(self, *data):
        from trepan.api import debug; debug()
        if (len(data) == 1) and data[0] == self.indent:
            diff = max(self.pending_newlines,
                       self.desired_line_number - self.current_line_number)
            self.f.write('\n'*diff)
            self.current_line_number += diff
            self.pending_newlines = 0
        if (len(data) == 0) or (len(data) == 1 and data[0] == ''):
            return

        out = ''.join((str(j) for j in data))
        n = 0
        for i in out:
            if i == '\n':
                n += 1
                if n == len(out):
                    self.pending_newlines = max(self.pending_newlines, n)
                    return
            elif n:
                self.pending_newlines = max(self.pending_newlines, n)
                out = out[n:]
                break
            else:
                break

        if self.pending_newlines > 0:
            diff = max(self.pending_newlines,
                       self.desired_line_number - self.current_line_number)
            self.f.write('\n'*diff)
            self.current_line_number += diff
            self.pending_newlines = 0

        for i in out[::-1]:
            if i == '\n':
                self.pending_newlines += 1
            else:
                break

        if self.pending_newlines:
            out = out[:-self.pending_newlines]
        self.f.write(out)
Пример #17
0
    def test_messages(self):
        code = ["General::foo", "Foo::bar", "Foo`Bar::baz"]
        from trepan.api import debug

        debug()
        expected = [
            [
                (MToken.BUILTIN, "General"),
                (MToken.OPERATOR, "::"),
                (MToken.MESSAGE, "foo"),
            ],
            [(MToken.SYMBOL, "Foo"), (MToken.OPERATOR, "::"),
             (MToken.MESSAGE, "bar")],
            [
                (MToken.SYMBOL, "Foo`Bar"),
                (MToken.OPERATOR, "::"),
                (MToken.MESSAGE, "baz"),
            ],
        ]
        self.verify_all(code, expected)
Пример #18
0
    def build_flowgraph(self, blocks, exit_block):
        g = DiGraph()

        self.block_offsets = {}
        self.block_nodes = {}

        # Add nodes
        for block in self.blocks:
            self.block_offsets[block.start_offset] = block
            block_node = g.make_add_node(block)
            self.block_nodes[block] = block_node
            self.offset2block[block.index[0]] = block_node
            pass

        self.exit_block = block_node
        # Compute a block's immediate predecessors and successors

        for block in self.blocks:

            for jump_offset in set(
                    block.jump_offsets) | block.exception_offsets:
                try:
                    assert jump_offset in self.block_offsets
                except:
                    from trepan.api import debug
                    debug()
                successor_block = self.block_offsets[jump_offset]
                successor_block.predecessors.add(block)
                block.successors.add(successor_block)
            if BB_NOFOLLOW in block.flags:
                exit_block.predecessors.add(block)
                block.successors.add(exit_block)
                pass
            elif (block.follow_offset and (not (jump_flags & block.flags))):
                assert block.follow_offset in self.block_offsets
                successor_block = self.block_offsets[block.follow_offset]
                successor_block.predecessors.add(block)
                block.successors.add(successor_block)
            pass

        assert (len(self.blocks) > 0)
        self.entry_node = self.blocks[0]

        sorted_blocks = sorted(self.blocks, key=attrgetter('index'))
        for i, block in enumerate(sorted_blocks):

            # Is this this dead code? (Remove self loops in calculation)
            # Entry node, blocks[0] is never unreachable
            if not block.predecessors - set([block]) and block != blocks[0]:
                block.unreachable = True

            block = sorted_blocks[i]
            if block.follow_offset:
                if BB_NOFOLLOW in block.flags:
                    kind = 'no fallthrough'
                    g.make_add_edge(self.block_nodes[block], self.exit_block,
                                    'exit edge')
                else:
                    kind = 'fallthrough'
                g.make_add_edge(
                    self.block_nodes[block],
                    self.block_nodes[self.block_offsets[block.follow_offset]],
                    kind)
            elif BB_EXIT not in block.flags:
                g.make_add_edge(self.block_nodes[block], self.exit_block,
                                'exit edge')

            # Connect the current block to its jump targets
            for jump_index in block.jump_offsets:
                target_block = self.block_offsets[jump_index]
                if jump_index > block.start_offset:
                    if BB_LOOP in block.flags:
                        edge_type = 'forward_scope'
                    else:
                        edge_type = 'forward'
                else:
                    edge_type = 'backward'
                    pass

                if self.block_nodes[target_block] == self.block_nodes[block]:
                    edge_type = 'self-loop'

                g.make_add_edge(self.block_nodes[block],
                                self.block_nodes[target_block], edge_type)
                pass
            for jump_index in block.exception_offsets:
                target_block = self.block_offsets[jump_index]
                assert jump_index >= block.start_offset
                edge_type = 'exception'
                g.make_add_edge(self.block_nodes[block],
                                self.block_nodes[target_block], edge_type)
                pass
            pass

        self.graph = g
        return
Пример #19
0
def get_url(q, url):
    if url == "http://bing.com":
        from trepan.api import debug;
        debug()
    q.put(urllib2.urlopen(url).read())
Пример #20
0
#!/usr/bin/env python
"""Something to use to test signal handling. Basically we just need
a program that installs a signal handler and sends it a signal.
"""
import sys, os, signal, time
from trepan.api import debug
debug()


def signal_handler(num, f):
    print 'signal %d received' % num
    return


signal.signal(signal.SIGUSR1, signal_handler)
sleepy_time = 4
print "pid %d" % os.getpid()
print "Waiting in time.sleep(%d) for signal USR1." % sleepy_time
while True:
    time.sleep(sleepy_time)
    os.kill(os.getpid(), signal.SIGUSR1)
    pass
pass
Пример #21
0
def get_url(q, url):
    if url == "http://bing.com":
        from trepan.api import debug
        debug()
    q.put(urllib2.urlopen(url).read())
Пример #22
0
def or_check(self, lhs, n, rule, ast, tokens, first, last):
    rhs = rule[1]

    # print("XXX", first, last, rule)
    # for t in range(first, last): print(tokens[t])
    # print("="*40)

    if (first, last) == (2, 6):
        from trepan.api import debug; debug()

    if rhs[0:2] in (("expr_jt", "expr"),
                    ("expr_jitop", "expr"),
                    ("expr_jit", "expr")):
        if tokens[last] in  ASSERT_OPS or tokens[last-1] in ASSERT_OPS:
            return True

        # The following test is be the most accurate. It prevents "or" from being
        # mistake for part of an "assert".
        # There one might conceivably be "expr or AssertionError" code, but the
        # likelihood of that is vanishingly small.
        # The below then is useful until we get better control-flow analysis.
        # Note it is too hard in the scanner right nowto turn the LOAD_GLOBAL into
        # int LOAD_ASSERT, however in 3.9ish code generation does this by default.
        load_global = tokens[last - 1]
        if load_global == "LOAD_GLOBAL" and load_global.attr == "AssertionError":
            return True

        first_offset = tokens[first].off2int()
        expr_jt = ast[0]

        if expr_jt == "expr_jitop":
            jump_true = expr_jt[1]
        else:
            jump_true = expr_jt[1][0]

        jmp_true_target = jump_true.attr

        last_token = tokens[last]
        last_token_offset = last_token.off2int()

        # FIXME: use instructions for all of this
        if jmp_true_target < first_offset:
            return False
        elif jmp_true_target < last_token_offset:
            return True

        # If the jmp is backwards
        if last_token == "POP_JUMP_IF_FALSE" and not self.version in (2.7, 3.5, 3.6):
            if last_token.attr < last_token_offset:
                # For a backwards loop, well compare to the instruction *after*
                # then POP_JUMP...
                last_token = tokens[last + 1]
            # HACK alert 3 is the Python < 3.6ish thing.
            # Convert to using instructions
            return not (
                (last_token_offset <= jmp_true_target <= last_token_offset + 3)
                or jmp_true_target < tokens[first].off2int()
            )
        elif last_token == "JUMP_FORWARD" and expr_jt.kind != "expr_jitop":
            # "or" has to fall through to the next statement
            # FIXME: use instructions for all of this
            return True


    return False
Пример #23
0
 def boxes_to_text(self, leaves=None, **options):
     from trepan.api import debug; debug()
     if not leaves:
         leaves = self._leaves
     return "-CompiledCode-"
Пример #24
0
    def detect_control_flow(self, offset, targets, inst_index):
        """
        Detect type of block structures and their boundaries to fix optimized jumps
        in python2.3+
        """

        code = self.code
        op = self.insts[inst_index].opcode

        # Detect parent structure
        parent = self.structs[0]
        start  = parent['start']
        end    = parent['end']

        # Pick inner-most parent for our offset
        for struct in self.structs:
            current_start = struct['start']
            current_end   = struct['end']
            if ((current_start <= offset < current_end)
                and (current_start >= start and current_end <= end)):
                start  = current_start
                end    = current_end
                parent = struct

        if op == self.opc.SETUP_LOOP:
            # We categorize loop types: 'for', 'while', 'while 1' with
            # possibly suffixes '-loop' and '-else'
            # Try to find the jump_back instruction of the loop.
            # It could be a return instruction.

            start += instruction_size(op, self.opc)
            target = self.get_target(offset)
            end    = self.restrict_to_parent(target, parent)
            self.setup_loops[target] = offset

            if target != end:
                self.fixed_jumps[offset] = end

            (line_no, next_line_byte) = self.lines[offset]
            jump_back = self.last_instr(start, end, self.opc.JUMP_ABSOLUTE,
                                            next_line_byte, False)

            if jump_back:
                jump_forward_offset = xdis.next_offset(code[jump_back], self.opc, jump_back)
            else:
                jump_forward_offset = None

            return_val_offset1 = self.prev[self.prev[end]]

            if (jump_back and jump_back != self.prev_op[end]
                and self.is_jump_forward(jump_forward_offset)):
                if (code[self.prev_op[end]] == self.opc.RETURN_VALUE or
                    (code[self.prev_op[end]] == self.opc.POP_BLOCK
                     and code[return_val_offset1] == self.opc.RETURN_VALUE)):
                    jump_back = None
            if not jump_back:
                # loop suite ends in return
                jump_back = self.last_instr(start, end, self.opc.RETURN_VALUE)
                if not jump_back:
                    return

                jb_inst = self.get_inst(jump_back)
                jump_back = self.next_offset(jb_inst.opcode, jump_back)

                if_offset = None
                if code[self.prev_op[next_line_byte]] not in self.pop_jump_tf:
                    if_offset = self.prev[next_line_byte]
                if if_offset:
                    loop_type = 'while'
                    self.ignore_if.add(if_offset)
                else:
                    loop_type = 'for'
                target = next_line_byte
                end = xdis.next_offset(code[jump_back], self.opc, jump_back)
            else:
                if self.get_target(jump_back) >= next_line_byte:
                    jump_back = self.last_instr(start, end, self.opc.JUMP_ABSOLUTE, start, False)

                jb_inst = self.get_inst(jump_back)

                jb_next_offset = self.next_offset(jb_inst.opcode, jump_back)
                if end > jb_next_offset and self.is_jump_forward(end):
                    if self.is_jump_forward(jb_next_offset):
                        if self.get_target(jb_next_offset) == self.get_target(end):
                            self.fixed_jumps[offset] = jb_next_offset
                            end = jb_next_offset
                elif target < offset:
                    self.fixed_jumps[offset] = jb_next_offset
                    end = jb_next_offset

                target = self.get_target(jump_back)

                if code[target] in (self.opc.FOR_ITER, self.opc.GET_ITER):
                    loop_type = 'for'
                else:
                    loop_type = 'while'
                    test = self.prev_op[next_line_byte]

                    if test == offset:
                        loop_type = 'while 1'
                    elif self.code[test] in self.opc.JUMP_OPs:
                        self.ignore_if.add(test)
                        test_target = self.get_target(test)
                        if test_target > (jump_back+3):
                            jump_back = test_target
                self.not_continue.add(jump_back)
            self.loops.append(target)
            self.structs.append({'type': loop_type + '-loop',
                                 'start': target,
                                 'end':   jump_back})
            after_jump_offset = xdis.next_offset(code[jump_back], self.opc, jump_back)
            if after_jump_offset != end:
                self.structs.append({'type': loop_type + '-else',
                                     'start': after_jump_offset,
                                     'end':   end})
        elif op in self.pop_jump_tf:
            start   = offset + instruction_size(op, self.opc)
            target  = self.insts[inst_index].argval
            rtarget = self.restrict_to_parent(target, parent)
            prev_op = self.prev_op

            # Do not let jump to go out of parent struct bounds
            if target != rtarget and parent['type'] == 'and/or':
                self.fixed_jumps[offset] = rtarget
                return

            # Does this jump to right after another conditional jump that is
            # not myself?  If so, it's part of a larger conditional.
            # rocky: if we have a conditional jump to the next instruction, then
            # possibly I am "skipping over" a "pass" or null statement.
            pretarget = self.get_inst(prev_op[target])

            if (pretarget.opcode in self.pop_jump_if_pop and
                (target > offset) and pretarget.offset != offset):

                # FIXME: hack upon hack...
                # In some cases the pretarget can be a jump to the next instruction
                # and these aren't and/or's either. We limit to 3.5+ since we experienced there
                # but it might be earlier versions, or might be a general principle.
                if self.version < 3.5 or pretarget.argval != target:
                    # FIXME: this is not accurate The commented out below
                    # is what it should be. However grammar rules right now
                    # assume the incorrect offsets.
                    # self.fixed_jumps[offset] = target
                    self.fixed_jumps[offset] = pretarget.offset
                    self.structs.append({'type': 'and/or',
                                         'start': start,
                                         'end': pretarget.offset})
                    return

            # The opcode *two* instructions before the target jump offset is important
            # in making a determination of what we have. Save that.
            pre_rtarget = prev_op[rtarget]

            # Is it an "and" inside an "if" or "while" block
            if op == self.opc.POP_JUMP_IF_FALSE and self.version < 3.6:

                # Search for another POP_JUMP_IF_FALSE targetting the same op,
                # in current statement, starting from current offset, and filter
                # everything inside inner 'or' jumps and midline ifs
                match = self.rem_or(start, self.next_stmt[offset],
                                    self.opc.POP_JUMP_IF_FALSE, target)

                # If we still have any offsets in set, start working on it
                if match:
                    is_jump_forward = self.is_jump_forward(pre_rtarget)
                    if (is_jump_forward and pre_rtarget not in self.stmts and
                        self.restrict_to_parent(self.get_target(pre_rtarget), parent) == rtarget):
                        if (code[prev_op[pre_rtarget]] == self.opc.JUMP_ABSOLUTE
                            and self.remove_mid_line_ifs([offset]) and
                            target == self.get_target(prev_op[pre_rtarget]) and
                            (prev_op[pre_rtarget] not in self.stmts or
                             self.get_target(prev_op[pre_rtarget]) > prev_op[pre_rtarget]) and
                            1 == len(self.remove_mid_line_ifs(self.rem_or(start, prev_op[pre_rtarget], self.pop_jump_tf, target)))):
                            pass
                        elif (code[prev_op[pre_rtarget]] == self.opc.RETURN_VALUE
                              and self.remove_mid_line_ifs([offset]) and
                              1 == (len(set(self.remove_mid_line_ifs(self.rem_or(start, prev_op[pre_rtarget],
                                                                                 self.pop_jump_tf, target))) |
                                    set(self.remove_mid_line_ifs(self.rem_or(start, prev_op[pre_rtarget],
                                                                             (self.opc.POP_JUMP_IF_FALSE,
                                                                              self.opc.POP_JUMP_IF_TRUE,
                                                                              self.opc.JUMP_ABSOLUTE),
                                                                             pre_rtarget, True)))))):
                            pass
                        else:
                            fix = None
                            jump_ifs = self.inst_matches(start, self.next_stmt[offset],
                                                         self.opc.POP_JUMP_IF_FALSE)
                            last_jump_good = True
                            for j in jump_ifs:
                                if target == self.get_target(j):
                                    # FIXME: remove magic number
                                    if self.lines[j].next == j + 3 and last_jump_good:
                                        fix = j
                                        break
                                else:
                                    last_jump_good = False
                            self.fixed_jumps[offset] = fix or match[-1]
                            return
                    else:
                        self.fixed_jumps[offset] = match[-1]
                        return
            # op == POP_JUMP_IF_TRUE
            else:
                next = self.next_stmt[offset]
                if prev_op[next] == offset:
                    pass
                elif self.is_jump_forward(next) and target == self.get_target(next):
                    if code[prev_op[next]] == self.opc.POP_JUMP_IF_FALSE:
                        if (code[next] == self.opc.JUMP_FORWARD
                            or target != rtarget
                            or code[prev_op[pre_rtarget]] not in
                            (self.opc.JUMP_ABSOLUTE, self.opc.RETURN_VALUE)):
                            self.fixed_jumps[offset] = prev_op[next]
                            return
                elif (code[next] == self.opc.JUMP_ABSOLUTE and self.is_jump_forward(target) and
                      self.get_target(target) == self.get_target(next)):
                    self.fixed_jumps[offset] = prev_op[next]
                    return

            # Don't add a struct for a while test, it's already taken care of
            if offset in self.ignore_if:
                return

            rtarget_is_ja = code[pre_rtarget] == self.opc.JUMP_ABSOLUTE
            if ( rtarget_is_ja and
                pre_rtarget in self.stmts and
                pre_rtarget != offset and
                prev_op[pre_rtarget] != offset and
                not (code[rtarget] == self.opc.JUMP_ABSOLUTE and
                     code[rtarget+3] == self.opc.POP_BLOCK and
                     code[prev_op[pre_rtarget]] != self.opc.JUMP_ABSOLUTE)):
                rtarget = pre_rtarget

            # Does the "jump if" jump beyond a jump op?
            # That is, we have something like:
            #  POP_JUMP_IF_FALSE HERE
            #  ...
            # JUMP_FORWARD
            # HERE:
            #
            # If so, this can be block inside an "if" statement
            # or a conditional assignment like:
            #   x = 1 if x else 2
            #
            # For 3.5, in addition the JUMP_FORWARD above we could have
            # JUMP_BACK or CONTINUE
            #
            # There are other contexts we may need to consider
            # like whether the target is "END_FINALLY"
            # or if the condition jump is to a forward location
            if self.is_jump_forward(pre_rtarget) or (rtarget_is_ja and self.version >= 3.5):
                if_end = self.get_target(pre_rtarget)

                # If the jump target is back, we are looping
                if (if_end < pre_rtarget and
                    (code[prev_op[if_end]] == self.opc.SETUP_LOOP)):
                    if (if_end > start):
                        return

                end = self.restrict_to_parent(if_end, parent)

                self.structs.append({'type': 'if-then',
                                     'start': start,
                                     'end': pre_rtarget})

                # FIXME: add this
                # self.fixed_jumps[offset] = rtarget
                self.not_continue.add(pre_rtarget)

                if rtarget < end and (
                        code[rtarget] not in (self.opc.END_FINALLY,
                                              self.opc.JUMP_ABSOLUTE) and
                        code[prev_op[pre_rtarget]] not in (self.opc.POP_EXCEPT,
                                                        self.opc.END_FINALLY)):
                    self.structs.append({'type': 'else',
                                         'start': rtarget,
                                         'end': end})
                    self.else_start[rtarget] = end
            elif self.is_jump_back(pre_rtarget, 0):
                if_end = rtarget
                self.structs.append({'type': 'if-then',
                                     'start': start,
                                     'end': pre_rtarget})
                self.not_continue.add(pre_rtarget)
            elif code[pre_rtarget] in (self.opc.RETURN_VALUE,
                                       self.opc.BREAK_LOOP):
                self.structs.append({'type': 'if-then',
                                     'start': start,
                                     'end': rtarget})
                # It is important to distingish if this return is inside some sort
                # except block return
                jump_prev = prev_op[offset]
                if self.is_pypy and code[jump_prev] == self.opc.COMPARE_OP:
                    if self.opc.cmp_op[code[jump_prev+1]] == 'exception-match':
                        return
                if self.version >= 3.5:
                    # Python 3.5 may remove as dead code a JUMP
                    # instruction after a RETURN_VALUE. So we check
                    # based on seeing SETUP_EXCEPT various places.
                    if code[rtarget] == self.opc.SETUP_EXCEPT:
                        return
                    # Check that next instruction after pops and jump is
                    # not from SETUP_EXCEPT
                    next_op = rtarget
                    if code[next_op] == self.opc.POP_BLOCK:
                        next_op += instruction_size(self.code[next_op], self.opc)
                    if code[next_op] == self.opc.JUMP_ABSOLUTE:
                        next_op += instruction_size(self.code[next_op], self.opc)
                    if next_op in targets:
                        for try_op in targets[next_op]:
                            come_from_op = code[try_op]
                            if come_from_op == self.opc.SETUP_EXCEPT:
                                return
                            pass
                    pass
                if code[pre_rtarget] == self.opc.RETURN_VALUE:
                    # If we are at some sort of POP_JUMP_IF and the instruction before was
                    # COMPARE_OP exception-match, then pre_rtarget is not an end_if
                    if not (inst_index > 0 and self.insts[inst_index-1].argval == 'exception-match'):
                        self.return_end_ifs.add(pre_rtarget)
                else:
                    self.fixed_jumps[offset] = rtarget
                    self.not_continue.add(pre_rtarget)
            else:

                # FIXME: this is very convoluted and based on rather hacky
                # empirical evidence. It should go a way when
                # we have better control-flow analysis
                normal_jump = self.version >= 3.6
                if self.version == 3.5:
                    j = self.offset2inst_index[target]
                    if j+2 < len(self.insts) and self.insts[j+2].is_jump_target:
                        normal_jump = self.insts[j+1].opname == 'POP_BLOCK'

                if normal_jump:
                    # For now, we'll only tag forward jump.
                    if target > offset:
                        self.fixed_jumps[offset] = target
                        pass
                else:
                    # FIXME: This is probably a bug in < 3.5 and we should
                    # instead use the above code. But until we smoke things
                    # out we'll stick with it.
                    if rtarget > offset:
                        self.fixed_jumps[offset] = rtarget

        elif op == self.opc.SETUP_EXCEPT:
            target = self.get_target(offset)
            end    = self.restrict_to_parent(target, parent)
            self.fixed_jumps[offset] = end
        elif op == self.opc.POP_EXCEPT:
            next_offset = xdis.next_offset(op, self.opc, offset)
            target = self.get_target(next_offset)
            if target is None:
                from trepan.api import debug; debug()
            if target > next_offset:
                next_op = code[next_offset]
                if (self.opc.JUMP_ABSOLUTE == next_op and
                    self.opc.END_FINALLY != code[xdis.next_offset(next_op, self.opc, next_offset)]):
                    self.fixed_jumps[next_offset] = target
                    self.except_targets[target] = next_offset

        elif op == self.opc.SETUP_FINALLY:
            target = self.get_target(offset)
            end    = self.restrict_to_parent(target, parent)
            self.fixed_jumps[offset] = end
        elif op in self.jump_if_pop:
            target = self.get_target(offset)
            if target > offset:
                unop_target = self.last_instr(offset, target, self.opc.JUMP_FORWARD, target)
                if unop_target and code[unop_target+3] != self.opc.ROT_TWO:
                    self.fixed_jumps[offset] = unop_target
                else:
                    self.fixed_jumps[offset] = self.restrict_to_parent(target, parent)
                    pass
                pass
        elif self.version >= 3.5:
            # 3.5+ has Jump optimization which too often causes RETURN_VALUE to get
            # misclassified as RETURN_END_IF. Handle that here.
            # In RETURN_VALUE, JUMP_ABSOLUTE, RETURN_VALUE is never RETURN_END_IF
            if op == self.opc.RETURN_VALUE:
                next_offset = xdis.next_offset(op, self.opc, offset)
                if (next_offset < len(code) and code[next_offset] == self.opc.JUMP_ABSOLUTE and
                    offset in self.return_end_ifs):
                    self.return_end_ifs.remove(offset)
                    pass
                pass
            elif op == self.opc.JUMP_FORWARD:
                # If we have:
                #   JUMP_FORWARD x, [non-jump, insns], RETURN_VALUE, x:
                # then RETURN_VALUE is not RETURN_END_IF
                rtarget = self.get_target(offset)
                rtarget_prev = self.prev[rtarget]
                if (code[rtarget_prev] == self.opc.RETURN_VALUE and
                    rtarget_prev in self.return_end_ifs):
                    i = rtarget_prev
                    while i != offset:
                        if code[i] in [op3.JUMP_FORWARD, op3.JUMP_ABSOLUTE]:
                            return
                        i = self.prev[i]
                    self.return_end_ifs.remove(rtarget_prev)
                pass
        return
Пример #25
0
def signal_handler(num, f):
  logger.info("Caught sig handler.")
  from trepan.api import debug;
  debug(dbg_opts={'interface':Mserver.ServerInterface(connection_opts={'IO':'FIFO'})})
  return
Пример #26
0
    def extract(klass,
                frame_gen,
                *,
                limit=None,
                lookup_lines=True,
                capture_locals=False,
                lasti=None):
        """Create a StackSummary from a traceback or stack object.

        :param frame_gen: A generator that yields (frame, lineno) tuples to
            include in the stack.
        :param limit: None to include all frames or the number of frames to
            include.
        :param lookup_lines: If True, lookup lines for each frame immediately,
            otherwise lookup is deferred until the frame is rendered.
        :param capture_locals: If True, the local variables from each frame will
            be captured as object representations into the FrameSummary.
        :param last_i: If set, last instruction executed
        """
        if limit is None:
            limit = getattr(sys, "tracebacklimit", None)
            if limit is not None and limit < 0:
                limit = 0
        if limit is not None:
            if limit >= 0:
                frame_gen = itertools.islice(frame_gen, limit)
            else:
                frame_gen = collections.deque(frame_gen, maxlen=-limit)

        result = klass()
        fnames = set()
        try:
            for f, lineno, lasti in frame_gen:
                co = f.f_code
                filename = co.co_filename
                name = co.co_name

                fnames.add(filename)
                linecache.lazycache(filename, f.f_globals)
                # Must defer line lookups until we have called checkcache.
                if capture_locals:
                    f_locals = f.f_locals
                else:
                    f_locals = None

                result.append(
                    FrameSummary(
                        filename,
                        lineno,
                        name,
                        lookup_line=False,
                        locals=f_locals,
                        code=co,
                        last_i=lasti,
                    ))
        except:
            from trepan.api import debug

            debug()
        for filename in fnames:
            linecache.checkcache(filename)
        # If immediate lookup was desired, trigger lookups now.
        if lookup_lines:
            for f in result:
                f.line
        return result
Пример #27
0
    def build_flowgraph(self, blocks):
        g = DiGraph()

        self.block_offsets = {}
        self.block_nodes = {}

        # Add nodes
        for block in self.blocks:
            self.block_offsets[block.start_offset] = block
            block_node = g.make_add_node(block)
            self.block_nodes[block] = block_node

        # Compute a block's immediate predecessors and successors
        for block in self.blocks:
            for jump_offset in block.jump_offsets:
                try:
                    assert jump_offset in self.block_offsets
                except:
                    from trepan.api import debug

                    debug()
                    x = 1
                successor_block = self.block_offsets[jump_offset]
                successor_block.predecessors.add(block)
                block.successors.add(successor_block)
            if block.follow_offset and (not (jump_flags & block.flags or
                                             (BB_NOFOLLOW in block.flags))):
                assert block.follow_offset in self.block_offsets
                successor_block = self.block_offsets[block.follow_offset]
                successor_block.predecessors.add(block)
                block.successors.add(successor_block)

        assert len(self.blocks) > 0
        self.entry_node = self.blocks[0]

        sorted_blocks = sorted(self.blocks, key=attrgetter("index"))
        for i, block in enumerate(sorted_blocks):

            # Is this this dead code? (Remove self loops in calculation)
            # Entry node, blocks[0] is never unreachable
            if not block.predecessors - set([block]) and block != blocks[0]:
                block.unreachable = True

            block = sorted_blocks[i]
            if block.follow_offset:
                if BB_NOFOLLOW in block.flags:
                    kind = "no fallthrough"
                else:
                    kind = "fallthrough"
                g.make_add_edge(
                    self.block_nodes[block],
                    self.block_nodes[self.block_offsets[block.follow_offset]],
                    kind,
                )
            # Connect the current block to its jump targets
            for jump_index in block.jump_offsets:
                target_block = self.block_offsets[jump_index]
                if jump_index > block.start_offset:
                    if BB_LOOP in block.flags:
                        edge_type = "forward_scope"
                    else:
                        edge_type = "forward"
                else:
                    edge_type = "backward"

                if self.block_nodes[target_block] == self.block_nodes[block]:
                    edge_type = "self-loop"

                g.make_add_edge(self.block_nodes[block],
                                self.block_nodes[target_block], edge_type)
                pass
            pass

        self.graph = g
        return
Пример #28
0
def do_draw(self, cr, get_data_fn):

    if not self.exposed:
        if self.debug: print("Not exposed")
        return
    if self.debug: print("exposed")

    self.levels, self.pid2node = get_data_fn(self)

    max_x, max_y, self.levels_x = arrange(self.levels, self.pid2node,
                                          self.width, debug=self.debug)
    old_x, old_y = self.area.get_size_request()
    if old_x != max_x or old_y != max_y:
        self.area.set_size_request(max_x, max_y)

    if len(self.levels) == 0: return

    # cr.translate (10, 10)
    layout = PangoCairo.create_layout(cr)
    desc = Pango.font_description_from_string(self.font)
    layout.set_font_description(desc)

    x_offset = 0

    text_mid = self.fontHeight >> 1

    widths = {}

    for i, level in enumerate(self.levels):
        for pid in level:

            node = self.pid2node[pid]

            try:
                vrank, rank, x_offset, y_offset = node.PosInfo
            except:
                from trepan.api import debug; debug()

            # Draw line from process to parent
            if i > 0:
                layout.set_text('', -1)
                ppid = node.PPid
                parent = self.pid2node[ppid]

                pp_vrank, pp_i, pp_x, pp_y = parent.PosInfo
                pp_x += widths[ppid] + self.line_gap

                cr.move_to(x_offset - self.line_gap, y_offset + text_mid)
                cr.line_to(pp_x + self.line_gap, pp_y + text_mid)
                cr.set_source_rgba(0.0, 0.0, 0.0, 0.5)
                cr.stroke()
                pass

            # print(node.Name, node.PosInfo, node.State)
            PangoCairo.show_layout(cr, layout)

            cr.move_to(x_offset, y_offset)
            layout.set_text(node.Name, -1)

            text_width, text_height = layout.get_pixel_size()
            widths[pid] = text_width

            # layout and set process name
            if node.State[0] == 'R':
                cr.set_source_rgba(0.0, 1.0, 0.0, 1.0)
            elif node.State[0] == 'T':
                cr.set_source_rgba(1.0, 0.0, 0.0, 1.0)
            else:
                cr.set_source_rgba(0.0, 0.0, 0.0)

            if self.debug:
                print("xy(%d,%d), pid(%ld): %s" %
                      (node.PosInfo[2], node.PosInfo[3], node.Pid, node.Name))

            PangoCairo.show_layout(cr, layout)

            pass

    return
Пример #29
0
def err(msg, inst, i):
    msg += ". Instruction %d:\n%s" % (i, inst)
    from trepan.api import debug
    debug()
    raise RuntimeError(msg)
Пример #30
0
#!/usr/bin/env python
"""Something to use to test signal handling. Basically we just need
a program that installs a signal handler and sends it a signal.
"""
import sys, os, signal, time
from trepan.api import debug; debug()
def signal_handler(num, f):
    print 'signal %d received' % num
    return

signal.signal(signal.SIGUSR1, signal_handler)
sleepy_time = 4
print "pid %d" % os.getpid()
print "Waiting in time.sleep(%d) for signal USR1."  % sleepy_time
while True:
    time.sleep(sleepy_time)
    os.kill(os.getpid(), signal.SIGUSR1)
    pass
pass
Пример #31
0
    def detect_control_flow(self, offset: int, targets: Dict[Any, Any],
                            inst_index: int):
        """
        Detect type of block structures and their boundaries to fix optimized jumps
        in python2.3+
        """

        code = self.code
        inst = self.insts[inst_index]
        op = inst.opcode

        # Detect parent structure
        parent: Dict[str, int] = self.structs[0]
        start: int = parent["start"]
        end: int = parent["end"]

        # Pick inner-most parent for our offset
        for struct in self.structs:
            current_start = struct["start"]
            current_end = struct["end"]
            if (current_start <= offset < current_end) and (
                    current_start >= start and current_end <= end):
                start = current_start
                end = current_end
                parent = struct

        if self.version < 3.8 and op == self.opc.SETUP_LOOP:
            # We categorize loop types: 'for', 'while', 'while 1' with
            # possibly suffixes '-loop' and '-else'
            # Try to find the jump_back instruction of the loop.
            # It could be a return instruction.

            start += inst.inst_size
            target = self.get_target(offset)
            end = self.restrict_to_parent(target, parent)
            self.setup_loops[target] = offset

            if target != end:
                self.fixed_jumps[offset] = end

            (line_no, next_line_byte) = self.lines[offset]
            jump_back = self.last_instr(start, end, self.opc.JUMP_ABSOLUTE,
                                        next_line_byte, False)

            if jump_back:
                jump_forward_offset = xdis.next_offset(code[jump_back],
                                                       self.opc, jump_back)
            else:
                jump_forward_offset = None

            return_val_offset1 = self.prev[self.prev[end]]

            if (jump_back and jump_back != self.prev_op[end]
                    and self.is_jump_forward(jump_forward_offset)):
                if code[self.prev_op[end]] == self.opc.RETURN_VALUE or (
                        code[self.prev_op[end]] == self.opc.POP_BLOCK
                        and code[return_val_offset1] == self.opc.RETURN_VALUE):
                    jump_back = None
            if not jump_back:
                # loop suite ends in return
                jump_back = self.last_instr(start, end, self.opc.RETURN_VALUE)
                if not jump_back:
                    return

                jb_inst = self.get_inst(jump_back)
                jump_back = self.next_offset(jb_inst.opcode, jump_back)

                if_offset = None
                if code[self.prev_op[next_line_byte]] not in self.pop_jump_tf:
                    if_offset = self.prev[next_line_byte]
                if if_offset:
                    loop_type = "while"
                    self.ignore_if.add(if_offset)
                else:
                    loop_type = "for"
                target = next_line_byte
                end = xdis.next_offset(code[jump_back], self.opc, jump_back)
            else:
                if self.get_target(jump_back) >= next_line_byte:
                    jump_back = self.last_instr(start, end,
                                                self.opc.JUMP_ABSOLUTE, start,
                                                False)

                jb_inst = self.get_inst(jump_back)

                jb_next_offset = self.next_offset(jb_inst.opcode, jump_back)
                if end > jb_next_offset and self.is_jump_forward(end):
                    if self.is_jump_forward(jb_next_offset):
                        if self.get_target(jb_next_offset) == self.get_target(
                                end):
                            self.fixed_jumps[offset] = jb_next_offset
                            end = jb_next_offset
                elif target < offset:
                    self.fixed_jumps[offset] = jb_next_offset
                    end = jb_next_offset

                target = self.get_target(jump_back)

                if code[target] in (self.opc.FOR_ITER, self.opc.GET_ITER):
                    loop_type = "for"
                else:
                    loop_type = "while"
                    test = self.prev_op[next_line_byte]

                    if test == offset:
                        loop_type = "while 1"
                    elif self.code[test] in self.opc.JUMP_OPs:
                        self.ignore_if.add(test)
                        test_target = self.get_target(test)
                        if test_target > (jump_back + 3):
                            jump_back = test_target
                self.not_continue.add(jump_back)
            self.loops.append(target)
            self.structs.append({
                "type": loop_type + "-loop",
                "start": target,
                "end": jump_back
            })
            after_jump_offset = xdis.next_offset(code[jump_back], self.opc,
                                                 jump_back)
            if after_jump_offset != end:
                self.structs.append({
                    "type": loop_type + "-else",
                    "start": after_jump_offset,
                    "end": end,
                })
        elif op in self.pop_jump_tf:
            target = inst.argval
            self.fixed_jumps[offset] = target

        # FIXME: consider removing the test on 3.8.
        elif self.version >= 3.8 and inst.is_jump():
            self.fixed_jumps[offset] = inst.argval

        elif self.version < 3.8 and op == self.opc.SETUP_EXCEPT:
            target = self.get_target(offset)
            end = self.restrict_to_parent(target, parent)
            self.fixed_jumps[offset] = end
        elif self.version < 3.8 and op == self.opc.POP_EXCEPT:
            next_offset = xdis.next_offset(op, self.opc, offset)
            target = self.get_target(next_offset)
            if target > next_offset:
                next_op = code[next_offset]
                if (self.opc.JUMP_ABSOLUTE == next_op
                        and self.opc.END_FINALLY != code[xdis.next_offset(
                            next_op, self.opc, next_offset)]):
                    self.fixed_jumps[next_offset] = target
                    from trepan.api import debug
                    debug()
                    self.except_targets[target] = next_offset

        elif op == self.opc.SETUP_FINALLY:
            target = self.get_target(offset)
            end = self.restrict_to_parent(target, parent)
            self.fixed_jumps[offset] = end
        elif op in self.jump_if_pop:
            target = self.get_target(offset)
            if target > offset:
                unop_target = self.last_instr(offset, target,
                                              self.opc.JUMP_FORWARD, target)
                if unop_target and code[unop_target + 3] != self.opc.ROT_TWO:
                    self.fixed_jumps[offset] = unop_target
                else:
                    self.fixed_jumps[offset] = self.restrict_to_parent(
                        target, parent)
                    pass
                pass
        else:
            # 3.5+ has Jump optimization which too often causes RETURN_VALUE to get
            # misclassified as RETURN_END_IF. Handle that here.
            # In RETURN_VALUE, JUMP_ABSOLUTE, RETURN_VALUE is never RETURN_END_IF
            if op == self.opc.RETURN_VALUE:
                next_offset = xdis.next_offset(op, self.opc, offset)
                if next_offset < len(code) and (
                        code[next_offset] == self.opc.JUMP_ABSOLUTE
                        and offset in self.return_end_ifs):
                    self.return_end_ifs.remove(offset)
                    pass
                pass
            elif op == self.opc.JUMP_FORWARD:
                # If we have:
                #   JUMP_FORWARD x, [non-jump, insns], RETURN_VALUE, x:
                # then RETURN_VALUE is not RETURN_END_IF
                rtarget = self.get_target(offset)
                rtarget_prev = self.prev[rtarget]
                if (code[rtarget_prev] == self.opc.RETURN_VALUE
                        and rtarget_prev in self.return_end_ifs):
                    i = rtarget_prev
                    while i != offset:
                        if code[i] in [op3.JUMP_FORWARD, op3.JUMP_ABSOLUTE]:
                            return
                        i = self.prev[i]
                    self.return_end_ifs.remove(rtarget_prev)
                pass
        return