-
-
Notifications
You must be signed in to change notification settings - Fork 440
/
Copy pathrun_sysmon.py
110 lines (81 loc) · 3.37 KB
/
run_sysmon.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
"""Run sys.monitoring on a file of Python code."""
import functools
import sys
print(sys.version)
the_program = sys.argv[1]
code = compile(open(the_program).read(), filename=the_program, mode="exec")
my_id = sys.monitoring.COVERAGE_ID
sys.monitoring.use_tool_id(my_id, "run_sysmon.py")
register = functools.partial(sys.monitoring.register_callback, my_id)
events = sys.monitoring.events
def bytes_to_lines(code):
"""Make a dict mapping byte code offsets to line numbers."""
b2l = {}
cur_line = 0
for bstart, bend, lineno in code.co_lines():
for boffset in range(bstart, bend, 2):
b2l[boffset] = lineno
return b2l
def show_off(label, code, instruction_offset):
if code.co_filename == the_program:
b2l = bytes_to_lines(code)
print(f"{label}: {code.co_filename}@{instruction_offset} #{b2l[instruction_offset]}")
def show_line(label, code, line_number):
if code.co_filename == the_program:
print(f"{label}: {code.co_filename} #{line_number}")
def show_off_off(label, code, instruction_offset, destination_offset):
if code.co_filename == the_program:
b2l = bytes_to_lines(code)
print(
f"{label}: {code.co_filename}@{instruction_offset}->{destination_offset} "
+ f"#{b2l[instruction_offset]}->{b2l[destination_offset]}"
)
def sysmon_py_start(code, instruction_offset):
show_off("PY_START", code, instruction_offset)
sys.monitoring.set_local_events(
my_id,
code,
events.PY_RETURN
| events.PY_RESUME
| events.LINE
| events.BRANCH_TAKEN
| events.BRANCH_NOT_TAKEN
| events.JUMP,
)
def sysmon_py_resume(code, instruction_offset):
show_off("PY_RESUME", code, instruction_offset)
return sys.monitoring.DISABLE
def sysmon_py_return(code, instruction_offset, retval):
show_off("PY_RETURN", code, instruction_offset)
return sys.monitoring.DISABLE
def sysmon_line(code, line_number):
show_line("LINE", code, line_number)
return sys.monitoring.DISABLE
def sysmon_branch(code, instruction_offset, destination_offset):
show_off_off("BRANCH", code, instruction_offset, destination_offset)
return sys.monitoring.DISABLE
def sysmon_branch_taken(code, instruction_offset, destination_offset):
show_off_off("BRANCH_TAKEN", code, instruction_offset, destination_offset)
return sys.monitoring.DISABLE
def sysmon_branch_not_taken(code, instruction_offset, destination_offset):
show_off_off("BRANCH_NOT_TAKEN", code, instruction_offset, destination_offset)
return sys.monitoring.DISABLE
def sysmon_jump(code, instruction_offset, destination_offset):
show_off_off("JUMP", code, instruction_offset, destination_offset)
return sys.monitoring.DISABLE
sys.monitoring.set_events(
my_id,
events.PY_START | events.PY_UNWIND,
)
register(events.PY_START, sysmon_py_start)
register(events.PY_RESUME, sysmon_py_resume)
register(events.PY_RETURN, sysmon_py_return)
# register(events.PY_UNWIND, sysmon_py_unwind_arcs)
register(events.LINE, sysmon_line)
#register(events.BRANCH, sysmon_branch)
register(events.BRANCH_TAKEN, sysmon_branch_taken)
register(events.BRANCH_NOT_TAKEN, sysmon_branch_not_taken)
register(events.JUMP, sysmon_jump)
exec(code)