def disco_loop(opc, version, queue, real_out, dup_lines=False, show_bytes=False): """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(show_bytes=show_bytes) + "\n") for c in co.co_consts: if iscode(c): queue.append(c) pass pass
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 do_disassembly(self, func, expected): co = func.__code__ bytecode = Bytecode(co, opc) got = bytecode.dis() # Trim trailing blanks (if any). lines = got.split('\n') lines = [line.rstrip() for line in lines] expected = expected.split("\n") import difflib if expected != lines: self.fail("events did not match expectation:\n" + "\n".join(difflib.ndiff(expected, lines)))
def disco_loop_asm_format(opc, version, co, real_out): """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. """ for c in co.co_consts: if iscode(c): disco_loop_asm_format(opc, version, c, real_out) pass if co.co_name != '<module>' or co.co_filename: real_out.write("\n" + format_code_info(co, version) + "\n") bytecode = Bytecode(co, opc) real_out.write(bytecode.dis(asm_format=True) + "\n")
def do_disassembly(self, func, expected): co = func.__code__ bytecode = Bytecode(co, opc) got = bytecode.dis() # Trim trailing blanks (if any). lines = got.split('\n') lines = [line.rstrip() for line in lines] expected = expected.split("\n") import difflib if expected != lines: self.fail( "events did not match expectation:\n" + "\n".join(difflib.ndiff(expected, lines)))
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")
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. """ if version < 3.0: co = code2compat(co) else: co = code3compat(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 version < 3.0: c_compat = code2compat(c) else: c_compat = code3compat(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=True) + "\n")