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
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)
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)