OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #ifndef BIN_DBG_MESSAGE_H_ | |
6 #define BIN_DBG_MESSAGE_H_ | |
7 | |
8 #include "bin/builtin.h" | |
9 #include "bin/thread.h" | |
10 #include "bin/utils.h" | |
11 | |
12 #include "include/dart_tools_api.h" | |
13 | |
14 #include "platform/globals.h" | |
15 #include "platform/json.h" | |
16 | |
17 | |
18 namespace dart { | |
19 namespace bin { | |
20 | |
21 // TODO(hausner): Need better error handling. | |
22 #define ASSERT_NOT_ERROR(handle) \ | |
23 ASSERT(!Dart_IsError(handle)) | |
24 | |
25 #define RETURN_IF_ERROR(handle) \ | |
26 if (Dart_IsError(handle)) { \ | |
27 return Dart_GetError(handle); \ | |
28 } | |
29 | |
30 | |
31 // Class to parse a JSON debug command message. | |
32 class MessageParser { | |
33 public: | |
34 MessageParser(const char* buf, int buf_length) | |
35 : buf_(buf), buf_length_(buf_length) { | |
36 } | |
37 ~MessageParser() { } | |
38 | |
39 // Accessors. | |
40 const char* buf() const { return buf_; } | |
41 | |
42 bool IsValidMessage() const; | |
43 int MessageId() const; | |
44 | |
45 const char* Params() const; | |
46 bool HasParam(const char* name) const; | |
47 intptr_t GetIntParam(const char* name) const; | |
48 int64_t GetInt64Param(const char* name) const; | |
49 intptr_t GetOptIntParam(const char* name, intptr_t default_val) const; | |
50 | |
51 // GetStringParam mallocs the buffer that it returns. Caller must free. | |
52 char* GetStringParam(const char* name) const; | |
53 | |
54 private: | |
55 const char* buf_; | |
56 int buf_length_; | |
57 | |
58 DISALLOW_COPY_AND_ASSIGN(MessageParser); | |
59 }; | |
60 | |
61 | |
62 // Class which represents a debug command message and handles it. | |
63 class DbgMessage { | |
64 public: | |
65 DbgMessage(int32_t cmd_idx, const char* start, | |
66 const char* end, intptr_t debug_fd) | |
67 : next_(NULL), cmd_idx_(cmd_idx), | |
68 buffer_(NULL), buffer_len_(end - start), | |
69 debug_fd_(debug_fd) { | |
70 buffer_ = reinterpret_cast<char*>(malloc(buffer_len_)); | |
71 ASSERT(buffer_ != NULL); | |
72 memmove(buffer_, start, buffer_len_); | |
73 } | |
74 ~DbgMessage() { | |
75 next_ = NULL; | |
76 free(buffer_); | |
77 } | |
78 | |
79 // Accessors. | |
80 DbgMessage* next() const { return next_; } | |
81 void set_next(DbgMessage* next) { next_ = next; } | |
82 char* buffer() const { return buffer_; } | |
83 int32_t buffer_len() const { return buffer_len_; } | |
84 intptr_t debug_fd() const { return debug_fd_; } | |
85 | |
86 // Handle debugger command message. | |
87 // Returns true if the execution needs to resume after this message is | |
88 // handled, false otherwise. | |
89 bool HandleMessage(); | |
90 | |
91 // Send reply after successful handling of command. | |
92 void SendReply(dart::TextBuffer* msg); | |
93 | |
94 // Reply error returned by the command handler. | |
95 void SendErrorReply(int msg_id, const char* err_msg); | |
96 | |
97 // Handlers for specific commands, they are static because these | |
98 // functions are populated as function pointers into a dispatch table. | |
99 static bool HandleResumeCmd(DbgMessage* msg); | |
100 static bool HandleStepIntoCmd(DbgMessage* msg); | |
101 static bool HandleStepOverCmd(DbgMessage* msg); | |
102 static bool HandleStepOutCmd(DbgMessage* msg); | |
103 static bool HandleGetLibrariesCmd(DbgMessage* msg); | |
104 static bool HandleGetClassPropsCmd(DbgMessage* msg); | |
105 static bool HandleGetLibPropsCmd(DbgMessage* msg); | |
106 static bool HandleSetLibPropsCmd(DbgMessage* msg); | |
107 static bool HandleGetGlobalsCmd(DbgMessage* msg); | |
108 static bool HandleEvaluateExprCmd(DbgMessage* msg); | |
109 static bool HandleGetObjPropsCmd(DbgMessage* msg); | |
110 static bool HandleGetListCmd(DbgMessage* msg); | |
111 static bool HandleGetScriptURLsCmd(DbgMessage* msg); | |
112 static bool HandleGetSourceCmd(DbgMessage* msg); | |
113 static bool HandleGetLineNumbersCmd(DbgMessage* msg); | |
114 static bool HandleGetStackTraceCmd(DbgMessage* msg); | |
115 static bool HandlePauseOnExcCmd(DbgMessage* msg); | |
116 static bool HandleSetBpCmd(DbgMessage* msg); | |
117 static bool HandleRemBpCmd(DbgMessage* msg); | |
118 | |
119 private: | |
120 DbgMessage* next_; // Next message in the queue. | |
121 int32_t cmd_idx_; // Isolate specific debugger command index. | |
122 char* buffer_; // Debugger command message. | |
123 int32_t buffer_len_; // Length of the debugger command message. | |
124 intptr_t debug_fd_; // Debugger connection on which replies are to be sent. | |
125 | |
126 DISALLOW_IMPLICIT_CONSTRUCTORS(DbgMessage); | |
127 }; | |
128 | |
129 | |
130 // Class which represents a queue of debug command messages sent to an isolate. | |
131 class DbgMsgQueue { | |
132 public: | |
133 DbgMsgQueue(Dart_IsolateId isolate_id, DbgMsgQueue* next) | |
134 : is_running_(true), | |
135 is_interrupted_(false), | |
136 msglist_head_(NULL), | |
137 msglist_tail_(NULL), | |
138 queued_output_messages_(64), | |
139 isolate_id_(isolate_id), | |
140 next_(next) { | |
141 } | |
142 ~DbgMsgQueue() { | |
143 DbgMessage* msg = msglist_head_; | |
144 while (msglist_head_ != NULL) { | |
145 msglist_head_ = msglist_head_->next(); | |
146 delete msg; | |
147 msg = msglist_head_; | |
148 } | |
149 msglist_tail_ = NULL; | |
150 isolate_id_ = ILLEGAL_ISOLATE_ID; | |
151 next_ = NULL; | |
152 } | |
153 | |
154 // Accessors. | |
155 Dart_IsolateId isolate_id() const { return isolate_id_; } | |
156 DbgMsgQueue* next() const { return next_; } | |
157 void set_next(DbgMsgQueue* next) { next_ = next; } | |
158 | |
159 // Add specified debug command message to the queue. | |
160 void AddMessage(int32_t cmd_idx, | |
161 const char* start, | |
162 const char* end, | |
163 intptr_t debug_fd); | |
164 | |
165 // Notify an isolate of a pending vmservice message. | |
166 void Notify(); | |
167 | |
168 // Run a message loop which handles messages as they arrive until | |
169 // normal program execution resumes. | |
170 void MessageLoop(); | |
171 | |
172 // Handle any pending debug command messages in the queue. Return | |
173 // value indicates whether a resume has been requested. | |
174 bool HandlePendingMessages(); | |
175 | |
176 // Interrupt Isolate. | |
177 void InterruptIsolate(); | |
178 | |
179 // Queue output messages, these are sent out when we hit an event. | |
180 void QueueOutputMsg(dart::TextBuffer* msg); | |
181 | |
182 // Send all queued messages over to the debugger. | |
183 void SendQueuedMsgs(); | |
184 | |
185 // Send breakpoint event message over to the debugger. | |
186 void SendBreakpointEvent(intptr_t bp_id, const Dart_CodeLocation& location); | |
187 | |
188 // Send Exception event message over to the debugger. | |
189 void SendExceptionEvent(Dart_Handle exception, Dart_StackTrace trace); | |
190 | |
191 // Send Isolate event message over to the debugger. | |
192 void SendIsolateEvent(Dart_IsolateId isolate_id, Dart_IsolateEvent kind); | |
193 | |
194 private: | |
195 bool is_running_; // True if isolate is running and not in the debugger loop. | |
196 bool is_interrupted_; // True if interrupt command is pending. | |
197 | |
198 DbgMessage* msglist_head_; // Start of debugger messages list. | |
199 DbgMessage* msglist_tail_; // End of debugger messages list. | |
200 | |
201 // Text buffer that accumulates messages to be output. | |
202 dart::TextBuffer queued_output_messages_; | |
203 | |
204 Dart_IsolateId isolate_id_; // Id of the isolate tied to this queue. | |
205 | |
206 DbgMsgQueue* next_; // Used for creating a list of message queues. | |
207 | |
208 // The isolate waits on this condition variable when it needs to process | |
209 // debug messages. | |
210 Monitor msg_queue_lock_; | |
211 | |
212 DISALLOW_COPY_AND_ASSIGN(DbgMsgQueue); | |
213 }; | |
214 | |
215 | |
216 // Maintains a list of message queues. | |
217 class DbgMsgQueueList { | |
218 public: | |
219 static const int32_t kInvalidCommand = -1; | |
220 | |
221 // Initialize the message queue processing by setting up the appropriate | |
222 // handlers. | |
223 static void Initialize(); | |
224 | |
225 // Parses the input message and returns the command index if the message | |
226 // contains a valid isolate specific command. | |
227 // It returns kInvalidCommand otherwise. | |
228 static int32_t LookupIsolateCommand(const char* buf, int32_t buflen); | |
229 | |
230 // Queue debugger message targetted for the isolate. | |
231 static bool AddIsolateMessage(Dart_IsolateId isolate_id, | |
232 int32_t cmd_idx, | |
233 const char* start, | |
234 const char* end, | |
235 intptr_t debug_fd); | |
236 | |
237 // Notify an isolate of a pending vmservice message. | |
238 static void NotifyIsolate(Dart_Isolate isolate); | |
239 | |
240 // Interrupt isolate. | |
241 static bool InterruptIsolate(Dart_IsolateId isolate_id); | |
242 | |
243 // Add Debugger Message Queue corresponding to the Isolate. | |
244 static DbgMsgQueue* AddIsolateMsgQueue(Dart_IsolateId isolate_id); | |
245 | |
246 // Get Debugger Message Queue corresponding to the Isolate. | |
247 static DbgMsgQueue* GetIsolateMsgQueue(Dart_IsolateId isolate_id); | |
248 | |
249 // Remove Debugger Message Queue corresponding to the Isolate. | |
250 static void RemoveIsolateMsgQueue(Dart_IsolateId isolate_id); | |
251 | |
252 // Generic handlers for breakpoints, exceptions and delayed breakpoint | |
253 // resolution. | |
254 static void BptResolvedHandler(Dart_IsolateId isolate_id, | |
255 intptr_t bp_id, | |
256 const Dart_CodeLocation& location); | |
257 static void PausedEventHandler(Dart_IsolateId isolate_id, | |
258 intptr_t bp_id, | |
259 const Dart_CodeLocation& loc); | |
260 static void ExceptionThrownHandler(Dart_IsolateId isolate_id, | |
261 Dart_Handle exception, | |
262 Dart_StackTrace stack_trace); | |
263 static void IsolateEventHandler(Dart_IsolateId isolate_id, | |
264 Dart_IsolateEvent kind); | |
265 | |
266 // Print list of isolate ids of all message queues into text buffer. | |
267 static void ListIsolateIds(dart::TextBuffer* msg); | |
268 | |
269 private: | |
270 static DbgMsgQueue* GetIsolateMsgQueueLocked(Dart_IsolateId isolate_id); | |
271 | |
272 static DbgMsgQueue* list_; | |
273 static Mutex* msg_queue_list_lock_; | |
274 | |
275 DISALLOW_ALLOCATION(); | |
276 DISALLOW_IMPLICIT_CONSTRUCTORS(DbgMsgQueueList); | |
277 }; | |
278 | |
279 } // namespace bin | |
280 } // namespace dart | |
281 | |
282 #endif // BIN_DBG_MESSAGE_H_ | |
OLD | NEW |