-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdebugger.go
131 lines (112 loc) · 2.66 KB
/
debugger.go
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
package main
import (
"time"
"github.com/deweerdt/gocui"
)
var debuggerRunning bool // STRICTLY READONLY
var debuggerBreakpoints []uint16 = []uint16{}
var debuggerEvents chan *DebuggerEvent
type EventEnum int
const (
DEBUGGER_RUN EventEnum = 0
DEBUGGER_STEP EventEnum = 1
DEBUGGER_BREAK EventEnum = 2
DEBUGGER_QUIT EventEnum = 3
)
type DebuggerEvent struct {
G *gocui.Gui
Event EventEnum
}
// 2^22 / 10^9
const cyclesPerNanosecond = 0.004194304
func debuggerLoop(events <-chan *DebuggerEvent) {
running := false
ticker := time.Tick(time.Millisecond)
var startCycle uint64
var startTime int64
var runGui *gocui.Gui
for {
select {
case ev := <-events:
switch ev.Event {
case DEBUGGER_RUN:
debuggerRunning = true
running = true
startCycle = cycles
startTime = time.Now().UnixNano()
runGui = ev.G
viewDisassemblerPcLock = false
debuggerUpdateGui(ev.G)
case DEBUGGER_STEP:
if !running {
Step()
viewDisassemblerPcLock = true
debuggerUpdateGui(ev.G)
}
case DEBUGGER_BREAK:
debuggerRunning = false
running = false
viewDisassemblerPcLock = true
debuggerUpdateGui(ev.G)
case DEBUGGER_QUIT:
return
}
case <-ticker:
if running {
for {
// step first to avoid double breakpoint issues
Step()
// check for breakpoints - stop running if found
if isBreakpoint(pc) {
debuggerBreak(runGui)
break
}
// if we're ahead of where we're meant to be, yield for now
now := time.Now().UnixNano()
expectedCycles := uint64(float64(now-startTime) * cyclesPerNanosecond)
if cycles > startCycle+expectedCycles {
break
}
}
}
}
}
}
func debuggerInit() {
debuggerEvents = make(chan *DebuggerEvent, 10)
go debuggerLoop(debuggerEvents)
}
func debuggerStep(g *gocui.Gui) {
debuggerEvents <- &DebuggerEvent{g, DEBUGGER_STEP}
}
func debuggerRun(g *gocui.Gui) {
debuggerEvents <- &DebuggerEvent{g, DEBUGGER_RUN}
}
func debuggerBreak(g *gocui.Gui) {
debuggerEvents <- &DebuggerEvent{g, DEBUGGER_BREAK}
}
func debuggerQuit() {
debuggerEvents <- &DebuggerEvent{nil, DEBUGGER_QUIT}
}
func debuggerUpdateGui(g *gocui.Gui) {
g.Execute(func(g *gocui.Gui) error { return nil })
}
func debuggerToggleBreakpoint(addr uint16) {
for i := 0; i < len(debuggerBreakpoints); i++ {
if debuggerBreakpoints[i] == addr {
// delete
debuggerBreakpoints = append(debuggerBreakpoints[:i], debuggerBreakpoints[i+1:]...)
return
}
}
// didn't find it, append
debuggerBreakpoints = append(debuggerBreakpoints, addr)
}
func isBreakpoint(addr uint16) bool {
for _, v := range debuggerBreakpoints {
if addr == v {
return true
}
}
return false
}