示例#1
0
def findlabels(code):
    """Detect all offsets in a byte code which are jump targets.

    Return the list of offsets.

    """
    labels = []
    n = len(code)
    i = offset = 0
    while i < n:
        op = ord(code[i])
        oparg = ord(code[i + 1])
        i += 2
        offset += 1
        if op >= HAVE_ARGUMENT:
            op, oparg, size = get_extended_opcode(code, i, op, oparg)
            i += size + size
            offset += size
            label = -1
            if op in hasjrel:
                label = offset + oparg
            elif op in hasjabs:
                label = oparg
            if label >= 0:
                if label not in labels:
                    labels.append(label)
    return labels
示例#2
0
def getargs(co):
    """Get information about the arguments accepted by a code object.

    Three things are returned: (args, varargs, varkw), where 'args' is
    a list of argument names (possibly containing nested lists), and
    'varargs' and 'varkw' are the names of the * and ** arguments or None."""

    if not iscode(co):
        raise TypeError("arg is not a code object")

    nargs = co.co_argcount
    names = co.co_varnames
    code = co.co_code
    codelen = len(code)
    args = list(names[:nargs])
    step = 0

    # The following acrobatics are for anonymous (tuple) arguments.
    for i in range(nargs):
        if args[i][:1] in ("", "."):
            stack, remain, count = [], [], []
            while step < codelen:
                op = ord(code[step])
                oparg = ord(code[step + 1])
                step += 2
                if op >= dis.HAVE_ARGUMENT:
                    op, value, size = dis.get_extended_opcode(code, step, op, oparg)
                    step += size + size
                    opname = dis.opname[op]
                    if opname in ("UNPACK_TUPLE", "UNPACK_SEQUENCE"):
                        remain.append(value)
                        count.append(value)
                    elif opname == "STORE_FAST":
                        stack.append(names[value])

                        # Special case for sublists of length 1: def foo((bar))
                        # doesn't generate the UNPACK_TUPLE bytecode, so if
                        # `remain` is empty here, we have such a sublist.
                        if not remain:
                            stack[0] = [stack[0]]
                            break
                        else:
                            remain[-1] = remain[-1] - 1
                            while remain[-1] == 0:
                                remain.pop()
                                size = count.pop()
                                stack[-size:] = [stack[-size:]]
                                if not remain:
                                    break
                                remain[-1] = remain[-1] - 1
                            if not remain:
                                break
            args[i] = stack[0]

    varargs = None
    if co.co_flags & CO_VARARGS:
        varargs = co.co_varnames[nargs]
        nargs = nargs + 1
    varkw = None
    if co.co_flags & CO_VARKEYWORDS:
        varkw = co.co_varnames[nargs]
    return Arguments(args, varargs, varkw)
示例#3
0
def common_disassemble(code, lasti, deep, linestarts, varnames, names, constants, frees):
    """Disassemble a code object."""

    def get_const(index):
        if constants:
            const = constants[index]
            if deep and type(const) in codeobject_types:
                code_objects.append(const)
            return repr(const)
        else:
            return "(%d)" % index

    def get_name(index):
        if names is not None:
            return names[index]
        else:
            return "(%d)" % index

    def get_varname(index):
        if varnames is not None:
            return varnames[index]
        else:
            return "(%d)" % index

    def get_free(index):
        if frees is not None:
            return frees[index]
        else:
            return "(%d)" % index

    global penultimate_op, last_op
    penultimate_op = last_op = 0
    labels = findlabels(code)
    n = len(code)
    i = offset = 0
    code_objects = []
    while i < n:
        op = ord(code[i])
        oparg = ord(code[i + 1])
        i += 2
        if offset in linestarts:
            if offset > 0:
                p()
            pc("%3d" % linestarts[offset])
        else:
            pc("   ")

        if offset == lasti:
            pc("-->")
        else:
            pc("   ")
        if offset in labels:
            pc(">>")
        else:
            pc("  ")
        pc(repr(offset).rjust(4))
        offset += 1
        if op >= HAVE_ARGUMENT:
            op, oparg, size = get_extended_opcode(code, i, op, oparg)
            i += size + size
            offset += size
            pc("len", size)
            pc(opname[op].ljust(25))
            if EXTENDED_ARG16 < op < EXTENDED_ARG32:
                pc("".rjust(5))
                if op == MOVE_FAST_FAST:
                    p(get_varname(oparg[0]) + " -> " + get_varname(oparg[1]))
                elif op == MOVE_CONST_FAST:
                    p(get_const(oparg[0]) + " -> " + get_varname(oparg[1]))
                elif op == MOVE_GLOBAL_FAST:
                    p(get_name(oparg[0]) + " -> " + get_varname(oparg[1]))
                elif op == MOVE_FAST_ATTR_FAST:
                    p(get_varname(oparg[0]) + "." + get_name(oparg[1]) + " -> " + get_varname(oparg[2]))
                elif op == MOVE_FAST_FAST_ATTR:
                    p(get_varname(oparg[0]) + " -> " + get_varname(oparg[1]) + "." + get_name(oparg[2]))
                elif op == MOVE_CONST_FAST_ATTR:
                    p(get_const(oparg[0]) + " -> " + get_varname(oparg[1]) + "." + get_name(oparg[2]))
                elif op == LOAD_FAST_ATTR:
                    p(get_varname(oparg[0]) + "." + get_name(oparg[1]))
            else:
                pc(repr(oparg).rjust(5))
                if op in hasconst:
                    pc("(" + get_const(oparg) + ")")
                elif op in hasname:
                    pc("(" + get_name(oparg) + ")")
                elif op in hasjrel:
                    pc("(to " + repr(offset + oparg) + ")")
                elif op in haslocal:
                    pc("(" + get_varname(oparg) + ")")
                elif op in hascompare:
                    pc("(" + cmp_op[oparg] + ")")
                elif op in hasfree:
                    pc("(" + get_free(oparg) + ")")
            size += 1
        else:
            size = 0
            pc("len", 1)
            pc(opname[op, oparg].ljust(30))
            if (op, oparg) in hascompare:
                pc(" (" + cmp_op[oparg - hascompare[0][1]] + ")")
        p()
        update_stats(op, oparg, size)

    check_code_objects(code_objects)