Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1246)

Side by Side Diff: runtime/bin/dbg_connection.cc

Issue 10392017: Support more debugger commands in the wire protocol (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "bin/dbg_connection.h" 5 #include "bin/dbg_connection.h"
6 #include "bin/dartutils.h" 6 #include "bin/dartutils.h"
7 #include "bin/socket.h" 7 #include "bin/socket.h"
8 #include "bin/thread.h" 8 #include "bin/thread.h"
9 #include "bin/utils.h" 9 #include "bin/utils.h"
10 10
11 #include "platform/globals.h" 11 #include "platform/globals.h"
12 #include "platform/json.h" 12 #include "platform/json.h"
13 #include "platform/thread.h" 13 #include "platform/thread.h"
14 #include "platform/utils.h" 14 #include "platform/utils.h"
15 15
16 #include "include/dart_api.h" 16 #include "include/dart_api.h"
17 17
18 18
19 int DebuggerConnectionHandler::listener_fd_ = -1; 19 int DebuggerConnectionHandler::listener_fd_ = -1;
20 int DebuggerConnectionHandler::debugger_fd_ = -1; 20 int DebuggerConnectionHandler::debugger_fd_ = -1;
21 dart::Monitor DebuggerConnectionHandler::is_connected_; 21 dart::Monitor DebuggerConnectionHandler::is_connected_;
22 MessageBuffer* DebuggerConnectionHandler::msgbuf_ = NULL; 22 MessageBuffer* DebuggerConnectionHandler::msgbuf_ = NULL;
23 23
24 bool DebuggerConnectionHandler::handler_started_ = false; 24 bool DebuggerConnectionHandler::handler_started_ = false;
25 bool DebuggerConnectionHandler::request_resume_ = false;
25 26
26 27
27 // TODO(hausner): Need better error handling. 28 // TODO(hausner): Need better error handling.
28 #define ASSERT_NOT_ERROR(handle) \ 29 #define ASSERT_NOT_ERROR(handle) \
29 ASSERT(!Dart_IsError(handle)) 30 ASSERT(!Dart_IsError(handle))
30 31
32 typedef void (*CommandHandler)(const char* json_cmd);
33
34 struct JSONDebuggerCommand {
35 const char* cmd_string;
36 CommandHandler handler_function;
37 };
38
31 39
32 class MessageBuffer { 40 class MessageBuffer {
33 public: 41 public:
34 explicit MessageBuffer(int fd); 42 explicit MessageBuffer(int fd);
35 ~MessageBuffer(); 43 ~MessageBuffer();
36 void ReadData(); 44 void ReadData();
37 bool IsValidMessage() const; 45 bool IsValidMessage() const;
38 void PopMessage(); 46 void PopMessage();
39 int MessageId() const; 47 int MessageId() const;
48 const char* Params() const;
40 char* buf() const { return buf_; } 49 char* buf() const { return buf_; }
41 bool Alive() const { return connection_is_alive_; } 50 bool Alive() const { return connection_is_alive_; }
42 51
43 private: 52 private:
44 static const int kInitialBufferSize = 256; 53 static const int kInitialBufferSize = 256;
45 char* buf_; 54 char* buf_;
46 int buf_length_; 55 int buf_length_;
47 int fd_; 56 int fd_;
48 int data_length_; 57 int data_length_;
49 bool connection_is_alive_; 58 bool connection_is_alive_;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 dart::JSONReader r(buf_); 97 dart::JSONReader r(buf_);
89 r.Seek("id"); 98 r.Seek("id");
90 if (r.Type() == dart::JSONReader::kInteger) { 99 if (r.Type() == dart::JSONReader::kInteger) {
91 return atoi(r.ValueChars()); 100 return atoi(r.ValueChars());
92 } else { 101 } else {
93 return -1; 102 return -1;
94 } 103 }
95 } 104 }
96 105
97 106
107 const char* MessageBuffer::Params() const {
108 dart::JSONReader r(buf_);
109 r.Seek("param");
110 if (r.Type() == dart::JSONReader::kObject) {
111 return r.ValueChars();
112 } else {
113 return NULL;
114 }
115 }
116
117
98 void MessageBuffer::ReadData() { 118 void MessageBuffer::ReadData() {
99 ASSERT(data_length_ >= 0); 119 ASSERT(data_length_ >= 0);
100 ASSERT(data_length_ < buf_length_); 120 ASSERT(data_length_ < buf_length_);
101 int max_read = buf_length_ - data_length_ - 1; 121 int max_read = buf_length_ - data_length_ - 1;
102 if (max_read == 0) { 122 if (max_read == 0) {
103 // TODO(hausner): 123 // TODO(hausner):
104 // Buffer is full. What should we do if there is no valid message 124 // Buffer is full. What should we do if there is no valid message
105 // in the buffer? This might be possible if the client sends a message 125 // in the buffer? This might be possible if the client sends a message
106 // that's larger than the buffer, of if the client sends malformed 126 // that's larger than the buffer, of if the client sends malformed
107 // messages that keep piling up. 127 // messages that keep piling up.
(...skipping 30 matching lines...) Expand all
138 } 158 }
139 } 159 }
140 160
141 161
142 static bool IsValidJSON(const char* msg) { 162 static bool IsValidJSON(const char* msg) {
143 dart::JSONReader r(msg); 163 dart::JSONReader r(msg);
144 return r.EndOfObject() != NULL; 164 return r.EndOfObject() != NULL;
145 } 165 }
146 166
147 167
148 void DebuggerConnectionHandler::HandleResumeCmd() { 168 void DebuggerConnectionHandler::SendError(int msg_id,
169 const char* format, ...) {
170 dart::TextBuffer msg(64);
171 msg.Printf("{\"id\": %d, \"error\": \"", msg_id);
172 va_list args;
173 va_start(args, format);
174 msg.Printf(format, args);
175 va_end(args);
176 msg.Printf("\"}");
177 Socket::Write(debugger_fd_, msg.buf(), msg.length());
178 // TODO(hausner): Error checking. Probably just shut down the debugger
179 // session if we there is an error while writing.
180 }
181
182
183 void DebuggerConnectionHandler::HandleResumeCmd(const char* json_msg) {
184 int msg_id = msgbuf_->MessageId();
185 dart::JSONReader r(json_msg);
siva 2012/05/10 20:08:36 This r object appears to be unused.
hausner 2012/05/10 22:36:28 Done.
186 dart::TextBuffer msg(64);
187 msg.Printf("{ \"id\": %d }", msg_id);
188 Socket::Write(debugger_fd_, msg.buf(), msg.length());
189 // TODO(hausner): Error checking. Probably just shut down the debugger
190 // session if we there is an error while writing.
191 request_resume_ = true;
192 }
193
194
195 void DebuggerConnectionHandler::HandleStepIntoCmd(const char* json_msg) {
196 Dart_Handle res = Dart_SetStepInto();
197 ASSERT_NOT_ERROR(res);
198 HandleResumeCmd(json_msg);
199 }
200
201
202 void DebuggerConnectionHandler::HandleStepOutCmd(const char* json_msg) {
203 Dart_Handle res = Dart_SetStepOut();
204 ASSERT_NOT_ERROR(res);
205 HandleResumeCmd(json_msg);
206 }
207
208
209 void DebuggerConnectionHandler::HandleStepOverCmd(const char* json_msg) {
210 Dart_Handle res = Dart_SetStepOver();
211 ASSERT_NOT_ERROR(res);
212 HandleResumeCmd(json_msg);
213 }
214
215
216 void DebuggerConnectionHandler::HandleGetScriptURLsCmd(const char* json_msg) {
149 int msg_id = msgbuf_->MessageId(); 217 int msg_id = msgbuf_->MessageId();
150 dart::TextBuffer msg(64); 218 dart::TextBuffer msg(64);
151 msg.Printf("{ \"id\": %d }", msg_id); 219 const char* params = msgbuf_->Params();
220 ASSERT(params != NULL);
221 dart::JSONReader pr(params);
222 pr.Seek("library");
223 ASSERT(pr.Type() == dart::JSONReader::kString);
224 char lib_url_chars[128];
225 pr.GetValueChars(lib_url_chars, sizeof(lib_url_chars));
226 Dart_Handle lib_url = Dart_NewString(lib_url_chars);
siva 2012/05/10 20:08:36 ASSERT(!Dart_IsError(lib_url));
hausner 2012/05/10 22:36:28 Done.
227 Dart_Handle urls = Dart_GetScriptURLs(lib_url);
228 if (Dart_IsError(urls)) {
229 SendError(msg_id, "Error: '%s'.", Dart_GetError(urls));
230 return;
231 }
232 ASSERT(Dart_IsList(urls));
233 intptr_t num_urls = 0;
234 Dart_ListLength(urls, &num_urls);
235 msg.Printf("{ \"id\": %d, ", msg_id);
236 msg.Printf("\"result\": { \"urls\": [");
237 for (int i = 0; i < num_urls; i++) {
238 Dart_Handle script_url = Dart_ListGetAt(urls, i);
239 ASSERT(Dart_IsString(script_url));
240 char const* chars;
241 Dart_StringToCString(lib_url, &chars);
siva 2012/05/10 20:08:36 See comments below about allocation of chars.
hausner 2012/05/10 22:36:28 Done.
242 msg.Printf("%s\"%s\"", (i == 0) ? "" : ", ", chars);
243 }
244 msg.Printf("] }}");
245 Socket::Write(debugger_fd_, msg.buf(), msg.length());
246 // TODO(hausner): Error checking. Probably just shut down the debugger
247 // session if we there is an error while writing.
248 }
249
250
251 void DebuggerConnectionHandler::HandleGetLibraryURLsCmd(const char* json_msg) {
252 int msg_id = msgbuf_->MessageId();
253 dart::TextBuffer msg(64);
254 msg.Printf("{ \"id\": %d, \"result\": { \"urls\": [", msg_id);
siva 2012/05/10 20:08:36 Does msg.Printf handle buffer overruns?
hausner 2012/05/10 22:36:28 Yes, it dynamically reallocs buffer space.
255 Dart_Handle urls = Dart_GetLibraryURLs();
siva 2012/05/10 20:08:36 ASSERT(!Dart_IsError(urls));
hausner 2012/05/10 22:36:28 Done.
256 intptr_t num_libs;
257 Dart_ListLength(urls, &num_libs);
258 for (int i = 0; i < num_libs; i++) {
259 Dart_Handle lib_url = Dart_ListGetAt(urls, i);
260 ASSERT(Dart_IsString(lib_url));
261 char const* chars;
262 Dart_StringToCString(lib_url, &chars);
siva 2012/05/10 20:08:36 chars is allocated in the ApiScope, do you create
hausner 2012/05/10 22:36:28 Thanks for this tip. Added a scope around the call
263 msg.Printf("%s\"%s\"", (i == 0) ? "" : ", ", chars);
264 }
265 msg.Printf("] }}");
152 Socket::Write(debugger_fd_, msg.buf(), msg.length()); 266 Socket::Write(debugger_fd_, msg.buf(), msg.length());
153 // TODO(hausner): Error checking. Probably just shut down the debugger 267 // TODO(hausner): Error checking. Probably just shut down the debugger
154 // session if we there is an error while writing. 268 // session if we there is an error while writing.
155 } 269 }
156 270
157 271
158 void DebuggerConnectionHandler::HandleMessages() { 272 void DebuggerConnectionHandler::HandleMessages() {
273 static JSONDebuggerCommand debugger_commands[] = {
274 { "resume", HandleResumeCmd },
275 { "getLibraryURLs", HandleGetLibraryURLsCmd},
276 { "getScriptURLs", HandleGetScriptURLsCmd },
277 { "stepInto", HandleStepIntoCmd },
278 { "stepOut", HandleStepOutCmd },
279 { "stepOver", HandleStepOverCmd },
280 { NULL, NULL }
281 };
282
159 for (;;) { 283 for (;;) {
160 while (!msgbuf_->IsValidMessage() && msgbuf_->Alive()) { 284 while (!msgbuf_->IsValidMessage() && msgbuf_->Alive()) {
161 msgbuf_->ReadData(); 285 msgbuf_->ReadData();
162 } 286 }
163 if (!msgbuf_->Alive()) { 287 if (!msgbuf_->Alive()) {
164 return; 288 return;
165 } 289 }
166 dart::JSONReader r(msgbuf_->buf()); 290 dart::JSONReader r(msgbuf_->buf());
167 bool found = r.Seek("command"); 291 bool found = r.Seek("command");
168 if (r.Error()) { 292 if (r.Error()) {
169 FATAL("Illegal JSON message received"); 293 FATAL("Illegal JSON message received");
170 } 294 }
171 if (!found) { 295 if (!found) {
172 printf("'command' not found in JSON message: '%s'\n", msgbuf_->buf()); 296 printf("'command' not found in JSON message: '%s'\n", msgbuf_->buf());
173 msgbuf_->PopMessage(); 297 msgbuf_->PopMessage();
174 } else if (r.IsStringLiteral("resume")) { 298 }
175 HandleResumeCmd(); 299 int i = 0;
176 msgbuf_->PopMessage(); 300 bool is_handled = false;
177 return; 301 request_resume_ = false;
178 } else { 302 while (debugger_commands[i].cmd_string != NULL) {
303 if (r.IsStringLiteral(debugger_commands[i].cmd_string)) {
304 is_handled = true;
305 (*debugger_commands[i].handler_function)(msgbuf_->buf());
306 msgbuf_->PopMessage();
307 if (request_resume_) {
308 return;
309 }
310 break;
311 }
312 i++;
313 }
314 if (!is_handled) {
siva 2012/05/10 20:08:36 It appears that the loop above could handle multip
hausner 2012/05/10 22:36:28 If a message is handled, the break statement in li
179 printf("unrecognized command received: '%s'\n", msgbuf_->buf()); 315 printf("unrecognized command received: '%s'\n", msgbuf_->buf());
180 msgbuf_->PopMessage(); 316 msgbuf_->PopMessage();
181 } 317 }
182 } 318 }
183 } 319 }
184 320
185 321
186 void DebuggerConnectionHandler::SendBreakpointEvent(Dart_Breakpoint bpt, 322 void DebuggerConnectionHandler::SendBreakpointEvent(Dart_Breakpoint bpt,
187 Dart_StackTrace trace) { 323 Dart_StackTrace trace) {
188 dart::TextBuffer msg(128); 324 dart::TextBuffer msg(128);
189 intptr_t trace_len = 0; 325 intptr_t trace_len = 0;
190 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len); 326 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len);
191 ASSERT_NOT_ERROR(res); 327 ASSERT_NOT_ERROR(res);
192 msg.Printf("{ \"command\" : \"paused\", \"params\" : "); 328 msg.Printf("{ \"event\": \"paused\", \"params\": ");
193 msg.Printf("{ \"callFrames\" : [ "); 329 msg.Printf("{ \"callFrames\" : [ ");
194 for (int i = 0; i < trace_len; i++) { 330 for (int i = 0; i < trace_len; i++) {
195 Dart_ActivationFrame frame; 331 Dart_ActivationFrame frame;
196 res = Dart_GetActivationFrame(trace, i, &frame); 332 res = Dart_GetActivationFrame(trace, i, &frame);
197 ASSERT_NOT_ERROR(res); 333 ASSERT_NOT_ERROR(res);
198 Dart_Handle func_name; 334 Dart_Handle func_name;
199 Dart_Handle script_url; 335 Dart_Handle script_url;
200 intptr_t line_number = 0; 336 intptr_t line_number = 0;
201 res = Dart_ActivationFrameInfo( 337 res = Dart_ActivationFrameInfo(
202 frame, &func_name, &script_url, &line_number); 338 frame, &func_name, &script_url, &line_number);
203 ASSERT_NOT_ERROR(res); 339 ASSERT_NOT_ERROR(res);
204 ASSERT(Dart_IsString(func_name)); 340 ASSERT(Dart_IsString(func_name));
205 const char* func_name_chars; 341 const char* func_name_chars;
206 Dart_StringToCString(func_name, &func_name_chars); 342 Dart_StringToCString(func_name, &func_name_chars);
207 msg.Printf("%s { \"functionName\" : \"%s\" , ", 343 msg.Printf("%s { \"functionName\": \"%s\" , ",
208 i > 0 ? "," : "", 344 i > 0 ? "," : "",
209 func_name_chars); 345 func_name_chars);
210 ASSERT(Dart_IsString(script_url)); 346 ASSERT(Dart_IsString(script_url));
211 const char* script_url_chars; 347 const char* script_url_chars;
212 Dart_StringToCString(script_url, &script_url_chars); 348 Dart_StringToCString(script_url, &script_url_chars);
213 msg.Printf("\"location\": { \"url\": \"%s\", \"lineNumber\": %d }}", 349 msg.Printf("\"location\": { \"url\": \"%s\", \"lineNumber\": %d }}",
214 script_url_chars, line_number); 350 script_url_chars, line_number);
215 } 351 }
216 msg.Printf("]}}"); 352 msg.Printf("]}}");
217 Socket::Write(debugger_fd_, msg.buf(), msg.length()); 353 Socket::Write(debugger_fd_, msg.buf(), msg.length());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 405
270 handler_started_ = true; 406 handler_started_ = true;
271 DebuggerConnectionImpl::StartHandler(port_number); 407 DebuggerConnectionImpl::StartHandler(port_number);
272 Dart_SetBreakpointHandler(BreakpointHandler); 408 Dart_SetBreakpointHandler(BreakpointHandler);
273 } 409 }
274 410
275 411
276 DebuggerConnectionHandler::~DebuggerConnectionHandler() { 412 DebuggerConnectionHandler::~DebuggerConnectionHandler() {
277 CloseDbgConnection(); 413 CloseDbgConnection();
278 } 414 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698