src/platform/python/mgba/debugger.py (view raw)
1# Copyright (c) 2013-2017 Jeffrey Pfau
2#
3# This Source Code Form is subject to the terms of the Mozilla Public
4# License, v. 2.0. If a copy of the MPL was not distributed with this
5# file, You can obtain one at http://mozilla.org/MPL/2.0/.
6from ._pylib import ffi, lib
7from .core import IRunner, ICoreOwner, Core
8import io
9import sys
10
11class DebuggerCoreOwner(ICoreOwner):
12 def __init__(self, debugger):
13 self.debugger = debugger
14 self.wasPaused = False
15
16 def claim(self):
17 if self.debugger.isRunning():
18 self.wasPaused = True
19 self.debugger.pause()
20 return self.debugger._core
21
22 def release(self):
23 if self.wasPaused:
24 self.debugger.unpause()
25
26class NativeDebugger(IRunner):
27 WATCHPOINT_WRITE = lib.WATCHPOINT_WRITE
28 WATCHPOINT_READ = lib.WATCHPOINT_READ
29 WATCHPOINT_RW = lib.WATCHPOINT_RW
30
31 BREAKPOINT_HARDWARE = lib.BREAKPOINT_HARDWARE
32 BREAKPOINT_SOFTWARE = lib.BREAKPOINT_SOFTWARE
33
34 ENTER_MANUAL = lib.DEBUGGER_ENTER_MANUAL
35 ENTER_ATTACHED = lib.DEBUGGER_ENTER_ATTACHED
36 ENTER_BREAKPOINT = lib.DEBUGGER_ENTER_BREAKPOINT
37 ENTER_WATCHPOINT = lib.DEBUGGER_ENTER_WATCHPOINT
38 ENTER_ILLEGAL_OP = lib.DEBUGGER_ENTER_ILLEGAL_OP
39
40 def __init__(self, native):
41 self._native = native
42 self._cbs = []
43 self._core = Core._detect(native.core)
44 self._core._load()
45
46 def pause(self):
47 lib.mDebuggerEnter(self._native, lib.DEBUGGER_ENTER_MANUAL, ffi.NULL)
48
49 def unpause(self):
50 self._native.state = lib.DEBUGGER_RUNNING
51
52 def isRunning(self):
53 return self._native.state == lib.DEBUGGER_RUNNING
54
55 def isPaused(self):
56 return self._native.state in (lib.DEBUGGER_PAUSED, lib.DEBUGGER_CUSTOM)
57
58 def useCore(self):
59 return DebuggerCoreOwner(self)
60
61 def setBreakpoint(self, address):
62 if not self._native.platform.setBreakpoint:
63 raise RuntimeError("Platform does not support breakpoints")
64 self._native.platform.setBreakpoint(self._native.platform, address)
65
66 def clearBreakpoint(self, address):
67 if not self._native.platform.setBreakpoint:
68 raise RuntimeError("Platform does not support breakpoints")
69 self._native.platform.clearBreakpoint(self._native.platform, address)
70
71 def setWatchpoint(self, address):
72 if not self._native.platform.setWatchpoint:
73 raise RuntimeError("Platform does not support watchpoints")
74 self._native.platform.setWatchpoint(self._native.platform, address)
75
76 def clearWatchpoint(self, address):
77 if not self._native.platform.clearWatchpoint:
78 raise RuntimeError("Platform does not support watchpoints")
79 self._native.platform.clearWatchpoint(self._native.platform, address)
80
81 def addCallback(self, cb):
82 self._cbs.append(cb)
83
84class CLIBackend(object):
85 def __init__(self, backend):
86 self.backend = backend
87
88 def write(self, string):
89 self.backend.printf(string)
90
91class CLIDebugger(NativeDebugger):
92 def __init__(self, native):
93 super(CLIDebugger, self).__init__(native)
94 self._cli = ffi.cast("struct CLIDebugger*", native)
95
96 def printf(self, message, *args, **kwargs):
97 message = message.format(*args, **kwargs)
98 self._cli.backend.printf(ffi.new("char []", b"%s"), ffi.new("char []", message.encode('utf-8')))
99
100 def installPrint(self):
101 sys.stdout = CLIBackend(self)