Skip to content

Commit 2762103

Browse files
author
rocky
committed
Add --method option to limit to specific methods
1 parent 698df9e commit 2762103

File tree

3 files changed

+41
-26
lines changed

3 files changed

+41
-26
lines changed

xdis/bin/pydisasm.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,22 @@
3737
),
3838
help="Select disassembly style",
3939
)
40+
@click.option(
41+
"--method",
42+
"-m",
43+
multiple=True,
44+
type=str,
45+
help="Specify a method name to filter disassembly by. Can be given multiple times.",
46+
)
47+
4048
@click.option(
4149
"--show-source/--no-show-source",
4250
"-S",
4351
help="Intersperse Python source text from linecache if available.",
4452
)
4553
@click.version_option(version=__version__)
4654
@click.argument("files", nargs=-1, type=click.Path(readable=True), required=True)
47-
def main(format, show_source: bool, files):
55+
def main(format, method: tuple, show_source: bool, files):
4856
"""Disassembles a Python bytecode file.
4957
5058
We handle bytecode for virtually every release of Python and some releases of PyPy.
@@ -80,7 +88,7 @@ def main(format, show_source: bool, files):
8088
continue
8189

8290
try:
83-
disassemble_file(path, sys.stdout, format, show_source=show_source)
91+
disassemble_file(path, sys.stdout, format, show_source=show_source, methods=method)
8492
except ImportError as e:
8593
print(e)
8694
rc = 3

xdis/disasm.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import sys
3030
import types
3131
from collections import deque
32+
from typing import Tuple
3233

3334
import xdis
3435
from xdis.bytecode import Bytecode
@@ -135,6 +136,7 @@ def disco(
135136
alternate_opmap=None,
136137
show_source=False,
137138
is_graal=False,
139+
methods=tuple(),
138140
):
139141
"""
140142
disassembles and deparses a given code block 'co'
@@ -160,7 +162,8 @@ def disco(
160162
real_out = out or sys.stdout
161163

162164
if co.co_filename and asm_format != "xasm":
163-
real_out.write(format_code_info(co, version_tuple, is_graal=is_graal) + "\n")
165+
if not_filtered(co, methods):
166+
real_out.write(format_code_info(co, version_tuple, is_graal=is_graal) + "\n")
164167
pass
165168

166169
opc = get_opcode(version_tuple, is_pypy, alternate_opmap)
@@ -180,6 +183,7 @@ def disco(
180183
asm_format=asm_format,
181184
dup_lines=True,
182185
show_source=show_source,
186+
methods=methods,
183187
)
184188

185189

@@ -191,6 +195,7 @@ def disco_loop(
191195
dup_lines=False,
192196
asm_format="classic",
193197
show_source=False,
198+
methods=tuple(),
194199
):
195200
"""Disassembles a queue of code objects. If we discover
196201
another code object which will be found in co_consts, we add
@@ -204,25 +209,26 @@ def disco_loop(
204209

205210
while len(queue) > 0:
206211
co = queue.popleft()
207-
if co.co_name not in ("<module>", "?"):
208-
real_out.write("\n" + format_code_info(co, version_tuple) + "\n")
209-
210-
if asm_format == "dis":
211-
assert version_tuple[:2] == PYTHON_VERSION_TRIPLE[:2], (
212-
"dis requires disassembly from the same Python version: "
213-
f"Bytecode is for {version_tuple[:2]}; Running:{PYTHON_VERSION_TRIPLE[:2]}"
214-
)
215-
dis.disassemble(co, lasti=-1, file=real_out)
216-
else:
217-
bytecode = Bytecode(co, opc, dup_lines=dup_lines)
218-
real_out.write(
219-
bytecode.dis(asm_format=asm_format, show_source=show_source) + "\n"
220-
)
212+
if not_filtered(co, methods):
213+
if co.co_name not in ("<module>", "?"):
214+
real_out.write("\n" + format_code_info(co, version_tuple) + "\n")
215+
216+
if asm_format == "dis":
217+
assert version_tuple[:2] == PYTHON_VERSION_TRIPLE[:2], (
218+
"dis requires disassembly from the same Python version: "
219+
f"Bytecode is for {version_tuple[:2]}; Running:{PYTHON_VERSION_TRIPLE[:2]}"
220+
)
221+
dis.disassemble(co, lasti=-1, file=real_out)
222+
else:
223+
bytecode = Bytecode(co, opc, dup_lines=dup_lines)
224+
real_out.write(
225+
bytecode.dis(asm_format=asm_format, show_source=show_source) + "\n"
226+
)
221227

222-
if version_tuple >= (3, 11):
223-
if bytecode.exception_entries not in (None, []):
224-
exception_table = format_exception_table(bytecode, version_tuple)
225-
real_out.write(exception_table + "\n")
228+
if version_tuple >= (3, 11):
229+
if bytecode.exception_entries not in (None, []):
230+
exception_table = format_exception_table(bytecode, version_tuple)
231+
real_out.write(exception_table + "\n")
226232

227233
for c in co.co_consts:
228234
if iscode(c):
@@ -312,6 +318,7 @@ def disassemble_file(
312318
asm_format="classic",
313319
alternate_opmap=None,
314320
show_source=False,
321+
methods: Tuple[str] = tuple()
315322
):
316323
"""
317324
Disassemble Python byte-code file (.pyc).
@@ -383,6 +390,7 @@ def disassemble_file(
383390
alternate_opmap=alternate_opmap,
384391
show_source=show_source,
385392
is_graal=is_graal,
393+
methods=methods,
386394
)
387395
# print co.co_filename
388396
return (
@@ -396,13 +404,16 @@ def disassemble_file(
396404
sip_hash,
397405
)
398406

407+
def not_filtered(co: types.CodeType, methods: tuple) -> bool:
408+
return len(methods) == 0 or co.co_name in methods
399409

400410
def _test():
401411
"""Simple test program to disassemble a file."""
402412
argc = len(sys.argv)
403413
if argc == 1:
404414
if xdis.PYTHON3:
405415
disassemble_file(__file__)
416+
disassemble_file(__file__, methods=("code_uniquify",))
406417
else:
407418
sys.stderr.write(f"usage: {__file__} [-|CPython compiled file [format]]\n")
408419
sys.exit(2)

xdis/marsh.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,11 @@
2929

3030
import struct
3131
import types
32+
from sys import intern
3233

3334
from xdis.codetype import Code2, Code3
3435
from xdis.version_info import PYTHON3, PYTHON_VERSION_TRIPLE, version_tuple_to_str
3536

36-
try:
37-
intern
38-
except NameError:
39-
from sys import intern
40-
4137
try:
4238
from __pypy__ import builtinify
4339

0 commit comments

Comments
 (0)