Ejemplo n.º 1
0
    def extract_prelude(cls, bytecode, co):
        ip = 0
        ip, n_state = upyopcodes.decode_varint(bytecode, ip)
        ip, n_exc_stack = upyopcodes.decode_varint(bytecode, ip)
        scope_flags = bytecode[ip]; ip += 1
        n_pos_args = bytecode[ip]; ip += 1
        n_kwonly_args = bytecode[ip]; ip += 1
        n_def_pos_args = bytecode[ip]; ip += 1
        ip2, code_info_size = upyopcodes.decode_varint(bytecode, ip)
        ip += code_info_size
        while bytecode[ip] != 0xff:
            ip += 1
        ip += 1
        # ip now points to first opcode
        # ip2 points to simple_name qstr

        co.mpy_stacksize = n_state
        co.mpy_excstacksize = n_exc_stack
        # Despite CPython docs saying "co_stacksize is the required stack
        # size (including local variables)", it's actually doesn't include
        # local variables (which function arguments being such too). This
        # was reported as https://bugs.python.org/issue38316 .
        # We don't readily have a number of local vars here, so at least
        # subtract number of arguments.
        co.co_stacksize = n_state - (n_pos_args + n_kwonly_args)
        co.co_argcount = n_pos_args
        co.co_kwonlyargcount = n_kwonly_args
        co.co_flags = scope_flags
        co.mpy_def_pos_args = n_def_pos_args
        return ip, ip2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args, code_info_size)
Ejemplo n.º 2
0
def disassemble(code, real_qstrs=False, qstr_ids=True):
    i = 0
    bc = code.co_code
    while i < len(bc):
        typ, sz = upyopcodes.mp_opcode_format(bc, i)
        # Handled by mp_opcode_format() above, but
        # config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
        # must be set correctly!
        #if bc[i] in upyopcodes.hascache:
        #    sz += 1
        print("% 15d " % i, end="")

        optarg = None
        opcode_str = opname[bc[i]]

        if typ == upyopcodes.MP_OPCODE_BYTE:
            # May have implict value encoded in the opcode
            implicit = op_implicit_arg[bc[i]]
            if implicit is not None:
                optarg = implicit

        elif typ == upyopcodes.MP_OPCODE_QSTR:
            optarg = bc[i + 1] + (bc[i + 2] << 8)
            if real_qstrs:
                s = qstr_by_id(optarg)
            else:
                s = code.co_names[optarg]
            if qstr_ids:
                optarg = "%d (%s)" % (optarg, s)
            else:
                optarg = s

        elif typ == upyopcodes.MP_OPCODE_VAR_UINT:
            signed = False
            if opcode_str == "LOAD_CONST_SMALL_INT":
                signed = True
            next_i, optarg = upyopcodes.decode_varint(bc, i + 1, signed=signed)
            if opcode_str.startswith("CALL_FUNCTION"):
                optarg = "n=%d nkw=%d" % (optarg & 0xff, optarg >> 8)
            elif opcode_str in ("LOAD_CONST_OBJ", "MAKE_FUNCTION",
                                "MAKE_FUNCTION_DEFARGS", "MAKE_CLOSURE"):
                optarg = "%d (%r)" % (optarg, code.co_consts[optarg])

            if opcode_str == "MAKE_CLOSURE":
                optarg += " n_closed=%d " % bc[next_i]

        elif typ == upyopcodes.MP_OPCODE_OFFSET:
            optarg = bc[i + 1] + (bc[i + 2] << 8) - 0x8000 + (i + sz)

        else:
            assert 0

        if optarg is not None:
            print("%-24s %s" % (opcode_str, optarg), end="")
        else:
            print("%-24s" % opcode_str, end="")

        if 0:
            print(" # t=%d sz=%d" % (typ, sz), end="")

        print()

        i += sz