-
Notifications
You must be signed in to change notification settings - Fork 2
/
debugger.py
141 lines (130 loc) · 4.23 KB
/
debugger.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#
# Simple micropython debugger, to be used at the same port where also the REPL is executed.
# Built on the settrace function which has been added by https://github.com/dpgeorge, at issue https://github.com/micropython/micropython/pull/5026
#
# mpconfigport.h has to be changed for this:
# define MICROPY_PY_SYS_SETTRACE (1) // To activate sys.settrace(tracefunc)
# define MICROPY_COMP_CONST (0) // required for MICROPY_PY_SYS_SETTRACE
# define MICROPY_PERSISTENT_CODE_SAVE (1) // required for MICROPY_PY_SYS_SETTRACE
import sys
import micropython
STATE_STEP=1
STATE_GO_NEXTBREAKPOINT=2
STATE_GO_NOBREAKPOINTS=3
STATE_GO_NOBREAKPOINTSTRACE=4
currState = STATE_STEP
breakpoints = {}
breakcounter = 0
show_breakcounter = False
def printFrame(frame, showCount=False):
if showCount == False:
print('File "%s", line %s, in %s' %(frame.f_code.co_filename, frame.f_lineno, frame.f_code.co_name))
else:
print('[%6d] File "%s", line %s, in %s' %(breakcounter, frame.f_code.co_filename, frame.f_lineno, frame.f_code.co_name))
#print(dir(frame))
#print(frame.f_globals)
def printTb(frame):
if frame.f_back:
printTb(frame.f_back)
printFrame(frame)
def doCommand(frame):
global currState
global breakcounter
global show_breakcounter
while True:
cmd = input("Debugger,? for help >")
if cmd == '?':
s = "help:\n<enter>:step\n'g' :go\n'gt' :go with linenr trace\n'n' :goto next break\n'b' :enter breakpoint\n'p' :print breakpoints\n'bt' :backtrace\n'bc' :toggle breakcounter\n'v' :print global variables\n'r' :REPL in current scope\n'm' :memory info"
print(s)
elif cmd == 'bc':
show_breakcounter = not(show_breakcounter)
elif cmd == 'b':
linenumber = None
file = None
while linenumber is None or file is None:
try:
file, linestr = input("Give file, line number:").split(",")
file = file.strip()
linenumber = int(linestr)
if file not in breakpoints:
breakpoints[file] = [linenumber]
else:
if linenumber not in breakpoints[file]:
breakpoints[file].append(linenumber)
except:
linenumber = None
file = None
print("Incorrect linenumber, try again")
elif cmd == "p":
if breakpoints == {}:
print("No breakpoints set.")
else:
for file in breakpoints:
print("file %s has breakpoints %s" %(file, breakpoints[file]))
elif cmd == "n":
currState = STATE_GO_NEXTBREAKPOINT
print("Running until next breakpoint...")
break
elif cmd == "":
currState = STATE_STEP
break
elif cmd == "g":
currState = STATE_GO_NOBREAKPOINTS
print("Running, exit debugger.")
break
elif cmd == "gt":
currState = STATE_GO_NOBREAKPOINTSTRACE
print("Running, with line number tracing, exit debugger.")
break
elif cmd == "bt":
printTb(frame)
elif cmd == 'v':
for v in frame.f_globals:
if str(type(frame.f_globals[v])) not in ["<class 'type'>", "<class 'function'>", "<class 'module'>" ]:
print("%s:%s %s" %(v, frame.f_globals[v], str(type(frame.f_globals[v]))))
elif cmd == 'r':
print("Entering REPL in current scope, CTRL-D to exit this REPL.")
while True:
try:
s = input(">>>")
except EOFError:
break #leave this repl.
try:
exec(s)
except Exception as e:
sys.print_exception(e)
elif cmd == "m":
print("memory usage figures:")
print("---------------------")
print("micropython.mem_info(1)")
micropython.mem_info(1)
print("micropython.stack_use=%s" %micropython.stack_use())
else:
print("Unknown command, please retry.")
def debugCb(frame, a, b):
global currState
global breakcounter
global show_breakcounter
breakcounter += 1
if currState == STATE_STEP:
print("Stopped at:", end='')
printFrame(frame)
doCommand(frame)
elif currState == STATE_GO_NEXTBREAKPOINT:
#check if we have hit a breakpoint
if frame.f_code.co_filename in breakpoints:
if frame.f_lineno in breakpoints[frame.f_code.co_filename]:
#hit
print("Stopped at:", end='')
printFrame(frame)
doCommand(frame)
elif currState == STATE_GO_NOBREAKPOINTS:
#do not check for breakpoints any more
pass
elif currState == STATE_GO_NOBREAKPOINTSTRACE:
printFrame(frame, show_breakcounter)
else:
print("state error")
return(debugCb)
def start():
sys.settrace(debugCb)