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

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

Issue 10383164: Debugger wire protocol: setting breakpoints (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 bool DebuggerConnectionHandler::request_resume_ = false;
26 26
27 dart::TextBuffer DebuggerConnectionHandler::queued_messages_(64);
28
27 29
28 // TODO(hausner): Need better error handling. 30 // TODO(hausner): Need better error handling.
29 #define ASSERT_NOT_ERROR(handle) \ 31 #define ASSERT_NOT_ERROR(handle) \
30 ASSERT(!Dart_IsError(handle)) 32 ASSERT(!Dart_IsError(handle))
31 33
32 typedef void (*CommandHandler)(const char* json_cmd); 34 typedef void (*CommandHandler)(const char* json_cmd);
33 35
34 struct JSONDebuggerCommand { 36 struct JSONDebuggerCommand {
35 const char* cmd_string; 37 const char* cmd_string;
36 CommandHandler handler_function; 38 CommandHandler handler_function;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 if (r.Type() == dart::JSONReader::kInteger) { 101 if (r.Type() == dart::JSONReader::kInteger) {
100 return atoi(r.ValueChars()); 102 return atoi(r.ValueChars());
101 } else { 103 } else {
102 return -1; 104 return -1;
103 } 105 }
104 } 106 }
105 107
106 108
107 const char* MessageBuffer::Params() const { 109 const char* MessageBuffer::Params() const {
108 dart::JSONReader r(buf_); 110 dart::JSONReader r(buf_);
109 r.Seek("param"); 111 r.Seek("params");
110 if (r.Type() == dart::JSONReader::kObject) { 112 if (r.Type() == dart::JSONReader::kObject) {
111 return r.ValueChars(); 113 return r.ValueChars();
112 } else { 114 } else {
113 return NULL; 115 return NULL;
114 } 116 }
115 } 117 }
116 118
117 119
118 void MessageBuffer::ReadData() { 120 void MessageBuffer::ReadData() {
119 ASSERT(data_length_ >= 0); 121 ASSERT(data_length_ >= 0);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 } 160 }
159 } 161 }
160 162
161 163
162 static bool IsValidJSON(const char* msg) { 164 static bool IsValidJSON(const char* msg) {
163 dart::JSONReader r(msg); 165 dart::JSONReader r(msg);
164 return r.EndOfObject() != NULL; 166 return r.EndOfObject() != NULL;
165 } 167 }
166 168
167 169
170 void DebuggerConnectionHandler::SendMsg(dart::TextBuffer* msg) {
171 ASSERT(debugger_fd_ >= 0);
172 Socket::Write(debugger_fd_, msg->buf(), msg->length());
173 // TODO(hausner): Error checking. Probably just shut down the debugger
174 // session if we there is an error while writing.
175 }
176
177
178 void DebuggerConnectionHandler::QueueMsg(dart::TextBuffer* msg) {
179 queued_messages_.Printf("%s", msg->buf());
180 }
181
182
183 void DebuggerConnectionHandler::SendQueuedMsgs() {
184 if (queued_messages_.length() > 0) {
185 SendMsg(&queued_messages_);
186 queued_messages_.Clear();
187 }
188 }
189
190
168 void DebuggerConnectionHandler::SendError(int msg_id, 191 void DebuggerConnectionHandler::SendError(int msg_id,
169 const char* err_msg) { 192 const char* err_msg) {
170 dart::TextBuffer msg(64); 193 dart::TextBuffer msg(64);
171 msg.Printf("{\"id\": %d, \"error\": \"Error: %s\"}", msg_id, err_msg); 194 msg.Printf("{\"id\": %d, \"error\": \"Error: %s\"}", msg_id, err_msg);
172 Socket::Write(debugger_fd_, msg.buf(), msg.length()); 195 SendMsg(&msg);
173 // TODO(hausner): Error checking. Probably just shut down the debugger
174 // session if we there is an error while writing.
175 } 196 }
176 197
177 198
178 void DebuggerConnectionHandler::HandleResumeCmd(const char* json_msg) { 199 void DebuggerConnectionHandler::HandleResumeCmd(const char* json_msg) {
179 int msg_id = msgbuf_->MessageId(); 200 int msg_id = msgbuf_->MessageId();
180 dart::TextBuffer msg(64); 201 dart::TextBuffer msg(64);
181 msg.Printf("{ \"id\": %d }", msg_id); 202 msg.Printf("{ \"id\": %d }", msg_id);
182 Socket::Write(debugger_fd_, msg.buf(), msg.length()); 203 SendMsg(&msg);
183 // TODO(hausner): Error checking. Probably just shut down the debugger
184 // session if we there is an error while writing.
185 request_resume_ = true; 204 request_resume_ = true;
186 } 205 }
187 206
188 207
189 void DebuggerConnectionHandler::HandleStepIntoCmd(const char* json_msg) { 208 void DebuggerConnectionHandler::HandleStepIntoCmd(const char* json_msg) {
190 Dart_Handle res = Dart_SetStepInto(); 209 Dart_Handle res = Dart_SetStepInto();
191 ASSERT_NOT_ERROR(res); 210 ASSERT_NOT_ERROR(res);
192 HandleResumeCmd(json_msg); 211 HandleResumeCmd(json_msg);
193 } 212 }
194 213
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 msg.Printf("{ \"id\": %d, ", msg_id); 249 msg.Printf("{ \"id\": %d, ", msg_id);
231 msg.Printf("\"result\": { \"urls\": ["); 250 msg.Printf("\"result\": { \"urls\": [");
232 for (int i = 0; i < num_urls; i++) { 251 for (int i = 0; i < num_urls; i++) {
233 Dart_Handle script_url = Dart_ListGetAt(urls, i); 252 Dart_Handle script_url = Dart_ListGetAt(urls, i);
234 ASSERT(Dart_IsString(script_url)); 253 ASSERT(Dart_IsString(script_url));
235 char const* chars; 254 char const* chars;
236 Dart_StringToCString(lib_url, &chars); 255 Dart_StringToCString(lib_url, &chars);
237 msg.Printf("%s\"%s\"", (i == 0) ? "" : ", ", chars); 256 msg.Printf("%s\"%s\"", (i == 0) ? "" : ", ", chars);
238 } 257 }
239 msg.Printf("] }}"); 258 msg.Printf("] }}");
240 Socket::Write(debugger_fd_, msg.buf(), msg.length()); 259 SendMsg(&msg);
241 // TODO(hausner): Error checking. Probably just shut down the debugger
242 // session if we there is an error while writing.
243 } 260 }
244 261
245 262
246 void DebuggerConnectionHandler::HandleGetLibraryURLsCmd(const char* json_msg) { 263 void DebuggerConnectionHandler::HandleGetLibraryURLsCmd(const char* json_msg) {
247 int msg_id = msgbuf_->MessageId(); 264 int msg_id = msgbuf_->MessageId();
248 dart::TextBuffer msg(64); 265 dart::TextBuffer msg(64);
249 msg.Printf("{ \"id\": %d, \"result\": { \"urls\": [", msg_id); 266 msg.Printf("{ \"id\": %d, \"result\": { \"urls\": [", msg_id);
250 Dart_Handle urls = Dart_GetLibraryURLs(); 267 Dart_Handle urls = Dart_GetLibraryURLs();
251 ASSERT_NOT_ERROR(urls); 268 ASSERT_NOT_ERROR(urls);
252 intptr_t num_libs; 269 intptr_t num_libs;
253 Dart_ListLength(urls, &num_libs); 270 Dart_ListLength(urls, &num_libs);
254 for (int i = 0; i < num_libs; i++) { 271 for (int i = 0; i < num_libs; i++) {
255 Dart_Handle lib_url = Dart_ListGetAt(urls, i); 272 Dart_Handle lib_url = Dart_ListGetAt(urls, i);
256 ASSERT(Dart_IsString(lib_url)); 273 ASSERT(Dart_IsString(lib_url));
257 char const* chars; 274 char const* chars;
258 Dart_StringToCString(lib_url, &chars); 275 Dart_StringToCString(lib_url, &chars);
259 msg.Printf("%s\"%s\"", (i == 0) ? "" : ", ", chars); 276 msg.Printf("%s\"%s\"", (i == 0) ? "" : ", ", chars);
260 } 277 }
261 msg.Printf("] }}"); 278 msg.Printf("] }}");
262 Socket::Write(debugger_fd_, msg.buf(), msg.length()); 279 SendMsg(&msg);
263 // TODO(hausner): Error checking. Probably just shut down the debugger 280 }
264 // session if we there is an error while writing. 281
282
283 static void FormatCallFrames(dart::TextBuffer* msg, Dart_StackTrace trace) {
284 intptr_t trace_len = 0;
285 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len);
286 ASSERT_NOT_ERROR(res);
287 msg->Printf("\"callFrames\" : [ ");
288 for (int i = 0; i < trace_len; i++) {
289 Dart_ActivationFrame frame;
290 res = Dart_GetActivationFrame(trace, i, &frame);
291 ASSERT_NOT_ERROR(res);
292 Dart_Handle func_name;
293 Dart_Handle script_url;
294 intptr_t line_number = 0;
295 res = Dart_ActivationFrameInfo(
296 frame, &func_name, &script_url, &line_number);
297 ASSERT_NOT_ERROR(res);
298 ASSERT(Dart_IsString(func_name));
299 const char* func_name_chars;
300 Dart_StringToCString(func_name, &func_name_chars);
301 msg->Printf("%s { \"functionName\": \"%s\" , ",
302 i > 0 ? "," : "",
303 func_name_chars);
304 ASSERT(Dart_IsString(script_url));
305 const char* script_url_chars;
306 Dart_StringToCString(script_url, &script_url_chars);
307 msg->Printf("\"location\": { \"url\": \"%s\", \"lineNumber\": %d }}",
308 script_url_chars, line_number);
309 }
310 msg->Printf("]");
311 }
312
313
314 void DebuggerConnectionHandler::HandleGetStackTraceCmd(const char* json_msg) {
315 int msg_id = msgbuf_->MessageId();
316 Dart_StackTrace trace;
317 Dart_Handle res = Dart_GetStackTrace(&trace);
318 ASSERT_NOT_ERROR(res);
319 dart::TextBuffer msg(128);
320 msg.Printf("{ \"id\": %d, \"result\": {", msg_id);
321 FormatCallFrames(&msg, trace);
322 msg.Printf("}}");
323 SendMsg(&msg);
324 }
325
326
327 void DebuggerConnectionHandler::HandleSetBpCmd(const char* json_msg) {
328 int msg_id = msgbuf_->MessageId();
329 const char* params = msgbuf_->Params();
330 ASSERT(params != NULL);
331 dart::JSONReader pr(params);
332 pr.Seek("url");
333 ASSERT(pr.Type() == dart::JSONReader::kString);
334 char url_chars[128];
335 pr.GetValueChars(url_chars, sizeof(url_chars));
336 Dart_Handle url = Dart_NewString(url_chars);
337 ASSERT_NOT_ERROR(url);
338 pr.Seek("line");
339 ASSERT(pr.Type() == dart::JSONReader::kInteger);
340 intptr_t line_number = atoi(pr.ValueChars());
341 Dart_Handle bp_id = Dart_SetBreakpoint(url, line_number);
342 if (Dart_IsError(bp_id)) {
343 SendError(msg_id, Dart_GetError(bp_id));
344 return;
345 }
346 ASSERT(Dart_IsInteger(bp_id));
347 uint64_t bp_id_value;
348 Dart_Handle res = Dart_IntegerToUint64(bp_id, &bp_id_value);
349 ASSERT_NOT_ERROR(res);
350 dart::TextBuffer msg(64);
351 msg.Printf("{ \"id\": %d, \"result\": { \"breakpointId\": %d }}",
352 msg_id, bp_id_value);
353 SendMsg(&msg);
354 }
355
356
357 void DebuggerConnectionHandler::HandleUnknownMsg(const char* json_msg) {
358 int msg_id = msgbuf_->MessageId();
359 ASSERT(msg_id >= 0);
360 SendError(msg_id, "unknown debugger command");
265 } 361 }
266 362
267 363
268 void DebuggerConnectionHandler::HandleMessages() { 364 void DebuggerConnectionHandler::HandleMessages() {
269 static JSONDebuggerCommand debugger_commands[] = { 365 static JSONDebuggerCommand debugger_commands[] = {
270 { "resume", HandleResumeCmd }, 366 { "resume", HandleResumeCmd },
271 { "getLibraryURLs", HandleGetLibraryURLsCmd}, 367 { "getLibraryURLs", HandleGetLibraryURLsCmd},
272 { "getScriptURLs", HandleGetScriptURLsCmd }, 368 { "getScriptURLs", HandleGetScriptURLsCmd },
369 { "getStackTrace", HandleGetStackTraceCmd },
370 { "setBreakpoint", HandleSetBpCmd },
273 { "stepInto", HandleStepIntoCmd }, 371 { "stepInto", HandleStepIntoCmd },
274 { "stepOut", HandleStepOutCmd }, 372 { "stepOut", HandleStepOutCmd },
275 { "stepOver", HandleStepOverCmd }, 373 { "stepOver", HandleStepOverCmd },
276 { NULL, NULL } 374 { NULL, NULL }
277 }; 375 };
278 376
279 for (;;) { 377 for (;;) {
378 SendQueuedMsgs();
280 while (!msgbuf_->IsValidMessage() && msgbuf_->Alive()) { 379 while (!msgbuf_->IsValidMessage() && msgbuf_->Alive()) {
281 msgbuf_->ReadData(); 380 msgbuf_->ReadData();
282 } 381 }
283 if (!msgbuf_->Alive()) { 382 if (!msgbuf_->Alive()) {
284 return; 383 return;
285 } 384 }
286 dart::JSONReader r(msgbuf_->buf()); 385 dart::JSONReader r(msgbuf_->buf());
287 bool found = r.Seek("command"); 386 bool found = r.Seek("command");
288 if (r.Error()) { 387 if (r.Error()) {
289 FATAL("Illegal JSON message received"); 388 FATAL("Illegal JSON message received");
(...skipping 12 matching lines...) Expand all
302 msgbuf_->PopMessage(); 401 msgbuf_->PopMessage();
303 if (request_resume_) { 402 if (request_resume_) {
304 return; 403 return;
305 } 404 }
306 break; 405 break;
307 } 406 }
308 i++; 407 i++;
309 } 408 }
310 if (!is_handled) { 409 if (!is_handled) {
311 printf("unrecognized command received: '%s'\n", msgbuf_->buf()); 410 printf("unrecognized command received: '%s'\n", msgbuf_->buf());
411 HandleUnknownMsg(msgbuf_->buf());
312 msgbuf_->PopMessage(); 412 msgbuf_->PopMessage();
313 } 413 }
314 } 414 }
315 } 415 }
316 416
317 417
318 void DebuggerConnectionHandler::SendBreakpointEvent(Dart_Breakpoint bpt, 418 void DebuggerConnectionHandler::SendBreakpointEvent(Dart_Breakpoint bpt,
319 Dart_StackTrace trace) { 419 Dart_StackTrace trace) {
320 dart::TextBuffer msg(128); 420 dart::TextBuffer msg(128);
321 intptr_t trace_len = 0; 421 msg.Printf("{ \"event\": \"paused\", \"params\": { ");
322 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len); 422 FormatCallFrames(&msg, trace);
323 ASSERT_NOT_ERROR(res); 423 msg.Printf("}}");
324 msg.Printf("{ \"event\": \"paused\", \"params\": ");
325 msg.Printf("{ \"callFrames\" : [ ");
326 for (int i = 0; i < trace_len; i++) {
327 Dart_ActivationFrame frame;
328 res = Dart_GetActivationFrame(trace, i, &frame);
329 ASSERT_NOT_ERROR(res);
330 Dart_Handle func_name;
331 Dart_Handle script_url;
332 intptr_t line_number = 0;
333 res = Dart_ActivationFrameInfo(
334 frame, &func_name, &script_url, &line_number);
335 ASSERT_NOT_ERROR(res);
336 ASSERT(Dart_IsString(func_name));
337 const char* func_name_chars;
338 Dart_StringToCString(func_name, &func_name_chars);
339 msg.Printf("%s { \"functionName\": \"%s\" , ",
340 i > 0 ? "," : "",
341 func_name_chars);
342 ASSERT(Dart_IsString(script_url));
343 const char* script_url_chars;
344 Dart_StringToCString(script_url, &script_url_chars);
345 msg.Printf("\"location\": { \"url\": \"%s\", \"lineNumber\": %d }}",
346 script_url_chars, line_number);
347 }
348 msg.Printf("]}}");
349 Socket::Write(debugger_fd_, msg.buf(), msg.length()); 424 Socket::Write(debugger_fd_, msg.buf(), msg.length());
350 ASSERT(IsValidJSON(msg.buf())); 425 ASSERT(IsValidJSON(msg.buf()));
351 } 426 }
352 427
353 428
354 void DebuggerConnectionHandler::BreakpointHandler(Dart_Breakpoint bpt, 429 void DebuggerConnectionHandler::BreakpointHandler(Dart_Breakpoint bpt,
355 Dart_StackTrace trace) { 430 Dart_StackTrace trace) {
356 { 431 {
357 MonitorLocker ml(&is_connected_); 432 MonitorLocker ml(&is_connected_);
358 while (!IsConnected()) { 433 while (!IsConnected()) {
359 printf("Waiting for debugger connection...\n"); 434 printf("Waiting for debugger connection...\n");
360 dart::Monitor::WaitResult res = ml.Wait(dart::Monitor::kNoTimeout); 435 dart::Monitor::WaitResult res = ml.Wait(dart::Monitor::kNoTimeout);
361 ASSERT(res == dart::Monitor::kNotified); 436 ASSERT(res == dart::Monitor::kNotified);
362 } 437 }
363 } 438 }
364 Dart_EnterScope(); 439 Dart_EnterScope();
440 SendQueuedMsgs();
365 SendBreakpointEvent(bpt, trace); 441 SendBreakpointEvent(bpt, trace);
366 HandleMessages(); 442 HandleMessages();
367 if (!msgbuf_->Alive()) { 443 if (!msgbuf_->Alive()) {
368 CloseDbgConnection(); 444 CloseDbgConnection();
369 } 445 }
370 Dart_ExitScope(); 446 Dart_ExitScope();
371 } 447 }
372 448
373 449
450 void DebuggerConnectionHandler::BptResolvedHandler(intptr_t bp_id,
451 Dart_Handle url,
452 intptr_t line_number) {
453 Dart_EnterScope();
454 dart::TextBuffer msg(128);
455 msg.Printf("{ \"event\": \"breakpointResolved\", \"params\": {");
456 msg.Printf("\"breakpointId\": %d, ", bp_id);
457 char const* url_chars;
458 Dart_StringToCString(url, &url_chars);
459 msg.Printf("\"url\": \"%s\", ", url_chars);
460 msg.Printf("\"line\": %d }}", line_number);
461 QueueMsg(&msg);
462 Dart_ExitScope();
463 }
464
465
374 void DebuggerConnectionHandler::AcceptDbgConnection(int debugger_fd) { 466 void DebuggerConnectionHandler::AcceptDbgConnection(int debugger_fd) {
375 debugger_fd_ = debugger_fd; 467 debugger_fd_ = debugger_fd;
376 ASSERT(msgbuf_ == NULL); 468 ASSERT(msgbuf_ == NULL);
377 msgbuf_ = new MessageBuffer(debugger_fd_); 469 msgbuf_ = new MessageBuffer(debugger_fd_);
378 { 470 {
379 MonitorLocker ml(&is_connected_); 471 MonitorLocker ml(&is_connected_);
380 ml.Notify(); 472 ml.Notify();
381 } 473 }
382 } 474 }
383 475
476
384 void DebuggerConnectionHandler::CloseDbgConnection() { 477 void DebuggerConnectionHandler::CloseDbgConnection() {
385 if (debugger_fd_ >= 0) { 478 if (debugger_fd_ >= 0) {
386 // TODO(hausner): need a Socket::Close() function. 479 // TODO(hausner): need a Socket::Close() function.
387 } 480 }
388 if (msgbuf_ != NULL) { 481 if (msgbuf_ != NULL) {
389 delete msgbuf_; 482 delete msgbuf_;
390 msgbuf_ = NULL; 483 msgbuf_ = NULL;
391 } 484 }
392 // TODO(hausner): Need to tell the VM debugger object to remove all 485 // TODO(hausner): Need to tell the VM debugger object to remove all
393 // breakpoints. 486 // breakpoints.
394 } 487 }
395 488
489
396 void DebuggerConnectionHandler::StartHandler(const char* address, 490 void DebuggerConnectionHandler::StartHandler(const char* address,
397 int port_number) { 491 int port_number) {
398 if (handler_started_) { 492 if (handler_started_) {
399 return; 493 return;
400 } 494 }
401 ASSERT(listener_fd_ == -1); 495 ASSERT(listener_fd_ == -1);
402 listener_fd_ = ServerSocket::CreateBindListen(address, port_number, 1); 496 listener_fd_ = ServerSocket::CreateBindListen(address, port_number, 1);
403 497
404 handler_started_ = true; 498 handler_started_ = true;
405 DebuggerConnectionImpl::StartHandler(port_number); 499 DebuggerConnectionImpl::StartHandler(port_number);
406 Dart_SetBreakpointHandler(BreakpointHandler); 500 Dart_SetBreakpointHandler(BreakpointHandler);
501 Dart_SetBreakpointResolvedHandler(BptResolvedHandler);
407 } 502 }
408 503
409 504
410 DebuggerConnectionHandler::~DebuggerConnectionHandler() { 505 DebuggerConnectionHandler::~DebuggerConnectionHandler() {
411 CloseDbgConnection(); 506 CloseDbgConnection();
412 } 507 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698