| 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 |