1 /* Copyright (c) 2013-2019 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/. */
6 #ifndef DEBUGGER_H
7 #define DEBUGGER_H
8 
9 #include <mgba-util/common.h>
10 
11 CXX_GUARD_START
12 
13 #include <mgba/core/cpu.h>
14 #include <mgba/core/log.h>
15 #include <mgba-util/vector.h>
16 #include <mgba/internal/debugger/stack-trace.h>
17 
18 mLOG_DECLARE_CATEGORY(DEBUGGER);
19 
20 extern const uint32_t DEBUGGER_ID;
21 
22 enum mDebuggerType {
23 	DEBUGGER_NONE = 0,
24 	DEBUGGER_CUSTOM,
25 	DEBUGGER_CLI,
26 	DEBUGGER_GDB,
27 	DEBUGGER_MAX
28 };
29 
30 enum mDebuggerState {
31 	DEBUGGER_PAUSED,
32 	DEBUGGER_RUNNING,
33 	DEBUGGER_CALLBACK,
34 	DEBUGGER_SHUTDOWN
35 };
36 
37 enum mWatchpointType {
38 	WATCHPOINT_WRITE = 1,
39 	WATCHPOINT_READ = 2,
40 	WATCHPOINT_RW = 3,
41 	WATCHPOINT_CHANGE = 4,
42 	WATCHPOINT_WRITE_CHANGE = 5,
43 };
44 
45 enum mBreakpointType {
46 	BREAKPOINT_HARDWARE,
47 	BREAKPOINT_SOFTWARE
48 };
49 
50 enum mDebuggerEntryReason {
51 	DEBUGGER_ENTER_MANUAL,
52 	DEBUGGER_ENTER_ATTACHED,
53 	DEBUGGER_ENTER_BREAKPOINT,
54 	DEBUGGER_ENTER_WATCHPOINT,
55 	DEBUGGER_ENTER_ILLEGAL_OP,
56 	DEBUGGER_ENTER_STACK
57 };
58 
59 struct mDebuggerEntryInfo {
60 	uint32_t address;
61 	union {
62 		struct {
63 			uint32_t oldValue;
64 			uint32_t newValue;
65 			enum mWatchpointType watchType;
66 			enum mWatchpointType accessType;
67 		} wp;
68 
69 		struct {
70 			uint32_t opcode;
71 			enum mBreakpointType breakType;
72 		} bp;
73 
74 		struct {
75 			enum mStackTraceMode traceType;
76 		} st;
77 	} type;
78 	ssize_t pointId;
79 };
80 
81 struct mBreakpoint {
82 	ssize_t id;
83 	uint32_t address;
84 	int segment;
85 	enum mBreakpointType type;
86 	struct ParseTree* condition;
87 };
88 
89 struct mWatchpoint {
90 	ssize_t id;
91 	uint32_t address;
92 	int segment;
93 	enum mWatchpointType type;
94 	struct ParseTree* condition;
95 };
96 
97 DECLARE_VECTOR(mBreakpointList, struct mBreakpoint);
98 DECLARE_VECTOR(mWatchpointList, struct mWatchpoint);
99 
100 struct mDebugger;
101 struct ParseTree;
102 struct mDebuggerPlatform {
103 	struct mDebugger* p;
104 
105 	void (*init)(void* cpu, struct mDebuggerPlatform*);
106 	void (*deinit)(struct mDebuggerPlatform*);
107 	void (*entered)(struct mDebuggerPlatform*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
108 
109 	bool (*hasBreakpoints)(struct mDebuggerPlatform*);
110 	void (*checkBreakpoints)(struct mDebuggerPlatform*);
111 	bool (*clearBreakpoint)(struct mDebuggerPlatform*, ssize_t id);
112 
113 	ssize_t (*setBreakpoint)(struct mDebuggerPlatform*, const struct mBreakpoint*);
114 	void (*listBreakpoints)(struct mDebuggerPlatform*, struct mBreakpointList*);
115 
116 	ssize_t (*setWatchpoint)(struct mDebuggerPlatform*, const struct mWatchpoint*);
117 	void (*listWatchpoints)(struct mDebuggerPlatform*, struct mWatchpointList*);
118 
119 	void (*trace)(struct mDebuggerPlatform*, char* out, size_t* length);
120 
121 	bool (*getRegister)(struct mDebuggerPlatform*, const char* name, int32_t* value);
122 	bool (*setRegister)(struct mDebuggerPlatform*, const char* name, int32_t value);
123 	bool (*lookupIdentifier)(struct mDebuggerPlatform*, const char* name, int32_t* value, int* segment);
124 
125 	uint32_t (*getStackTraceMode)(struct mDebuggerPlatform*);
126 	void (*setStackTraceMode)(struct mDebuggerPlatform*, uint32_t mode);
127 	bool (*updateStackTrace)(struct mDebuggerPlatform* d);
128 };
129 
130 struct mDebugger {
131 	struct mCPUComponent d;
132 	struct mDebuggerPlatform* platform;
133 	enum mDebuggerState state;
134 	enum mDebuggerType type;
135 	struct mCore* core;
136 	struct mScriptBridge* bridge;
137 	struct mStackTrace stackTrace;
138 
139 	void (*init)(struct mDebugger*);
140 	void (*deinit)(struct mDebugger*);
141 
142 	void (*paused)(struct mDebugger*);
143 	void (*entered)(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
144 	void (*custom)(struct mDebugger*);
145 };
146 
147 struct mDebugger* mDebuggerCreate(enum mDebuggerType type, struct mCore*);
148 void mDebuggerAttach(struct mDebugger*, struct mCore*);
149 void mDebuggerRun(struct mDebugger*);
150 void mDebuggerRunFrame(struct mDebugger*);
151 void mDebuggerEnter(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
152 
153 bool mDebuggerLookupIdentifier(struct mDebugger* debugger, const char* name, int32_t* value, int* segment);
154 
155 CXX_GUARD_END
156 
157 #endif
158