Example #1
0
def disco_loop(opc,
               version,
               queue,
               real_out,
               dup_lines=False,
               asm_format="classic"):
    """Disassembles a queue of code objects. If we discover
    another code object which will be found in co_consts, we add
    the new code to the list. Note that the order of code discovery
    is in the order of first encountered which is not amenable for
    the format used by a disassembler where code objects should
    be defined before using them in other functions.
    However this is not recursive and will overall lead to less
    memory consumption at run time.
    """

    while len(queue) > 0:
        co = queue.popleft()
        if co.co_name not in ("<module>", "?"):
            real_out.write("\n" + format_code_info(co, version) + "\n")

        bytecode = Bytecode(co, opc, dup_lines=dup_lines)
        real_out.write(bytecode.dis(asm_format=asm_format) + "\n")

        for c in co.co_consts:
            if iscode(c):
                queue.append(c)
            pass
        pass
 def _populate_lines(self):
     code = self.code
     last_line_info = None
     for instr in get_instructions_bytes(
         bytecode=code.co_code,
         opc=self.opc,
         varnames=code.co_varnames,
         names=code.co_names,
         constants=code.co_consts,
         cells=code.co_cellvars + code.co_freevars,
         linestarts=self.linestarts,
     ):
         offset = instr.offset
         self.offsets.append(offset)
         self.instructions.append(instr)
         if instr.starts_line:
             if last_line_info:
                 self.lines.append(last_line_info)
                 pass
             last_line_info = LineOffsets(instr.starts_line, [offset], code)
         else:
             last_line_info.offsets.append(offset)
             pass
         pass
     self.lines.append(last_line_info)
     if self.include_children:
         for c in code.co_consts:
             if iscode(c):
                 code_info = LineOffsetInfo(self.opc, c, True)
                 self.children[code_info.name] = code_info
                 self.lines += code_info.lines
                 pass
             pass
         pass
Example #3
0
def disco(
    bytecode_version,
    co,
    timestamp,
    out=sys.stdout,
    is_pypy=False,
    magic_int=None,
    source_size=None,
    sip_hash=None,
    asm_format="classic",
    show_bytes=False,
    dup_lines=False,
    alternate_opmap=None,
):
    """
    diassembles and deparses a given code block 'co'
    """

    assert iscode(co)

    show_module_header(
        bytecode_version,
        co,
        timestamp,
        out,
        is_pypy,
        magic_int,
        source_size,
        sip_hash,
        header=True,
        show_filename=False,
    )

    # store final output stream for case of error
    real_out = out or sys.stdout

    if co.co_filename and asm_format != "xasm":
        real_out.write(format_code_info(co, bytecode_version) + "\n")
        pass

    opc = get_opcode(bytecode_version, is_pypy, alternate_opmap)

    if asm_format == "xasm":
        disco_loop_asm_format(opc, bytecode_version, co, real_out, {}, set([]))
    else:
        queue = deque([co])
        disco_loop(opc,
                   bytecode_version,
                   queue,
                   real_out,
                   asm_format=asm_format,
                   dup_lines=True)
    def __init__(self, opc, code, include_children=False):
        if not iscode(code):
            raise TypeError(
                "code parameter %s needs to be a code type; is %s" % (code, type(code))
            )

        self.code = code
        self.name = code.co_name
        self.opc = opc
        self.children = {}
        self.lines = []
        self.offsets = []
        self.linestarts = dict(opc.findlinestarts(code, dup_lines=True))
        self.instructions = []
        self.include_children = include_children
        self._populate_lines()
        return
Example #5
0
def disco_loop_asm_format(opc, version, co, real_out, fn_name_map, all_fns):
    """Produces disassembly in a format more conducive to
    automatic assembly by producing inner modules before they are
    used by outer ones. Since this is recusive, we'll
    use more stack space at runtime.
    """

    co = codeType2Portable(co)
    co_name = co.co_name
    mapped_name = fn_name_map.get(co_name, co_name)

    new_consts = []
    for c in co.co_consts:
        if iscode(c):
            if isinstance(c, types.CodeType):
                c_compat = codeType2Portable(c)
            else:
                c_compat = c

            disco_loop_asm_format(opc, version, c_compat, real_out,
                                  fn_name_map, all_fns)

            m = re.match(".* object <(.+)> at", str(c))
            if m:
                basename = m.group(1)
                if basename != "module":
                    mapped_name = code_uniquify(basename, c.co_code)
                    c_compat.co_name = mapped_name
            c_compat.freeze()
            new_consts.append(c_compat)
        else:
            new_consts.append(c)
        pass
    co.co_consts = new_consts

    m = re.match("^<(.+)>$", co.co_name)
    if m or co_name in all_fns:
        if co_name in all_fns:
            basename = co_name
        else:
            basename = m.group(1)
        if basename != "module":
            mapped_name = code_uniquify(basename, co.co_code)
            co_name = mapped_name
            assert mapped_name not in fn_name_map
        fn_name_map[mapped_name] = basename
        co.co_name = mapped_name
        pass
    elif co_name in fn_name_map:
        # FIXME: better would be a hash of the co_code
        mapped_name = code_uniquify(co_name, co.co_code)
        fn_name_map[mapped_name] = co_name
        co.co_name = mapped_name
        pass

    co = co.freeze()
    all_fns.add(co_name)
    if co.co_name != "<module>" or co.co_filename:
        real_out.write("\n" + format_code_info(co, version, mapped_name) +
                       "\n")

    bytecode = Bytecode(co, opc, dup_lines=True)
    real_out.write(bytecode.dis(asm_format="asm") + "\n")