| OLD | NEW |
| 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 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 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); | 27 dart::TextBuffer DebuggerConnectionHandler::queued_messages_(64); |
| 28 | 28 |
| 29 | 29 |
| 30 // TODO(hausner): Need better error handling. | 30 // TODO(hausner): Need better error handling. |
| 31 #define ASSERT_NOT_ERROR(handle) \ | 31 #define ASSERT_NOT_ERROR(handle) \ |
| 32 ASSERT(!Dart_IsError(handle)) | 32 ASSERT(!Dart_IsError(handle)) |
| 33 | 33 |
| 34 #define RETURN_IF_ERROR(handle) \ |
| 35 if (Dart_IsError(handle)) { \ |
| 36 return Dart_GetError(handle); \ |
| 37 } |
| 38 |
| 39 |
| 34 typedef void (*CommandHandler)(const char* json_cmd); | 40 typedef void (*CommandHandler)(const char* json_cmd); |
| 35 | 41 |
| 36 struct JSONDebuggerCommand { | 42 struct JSONDebuggerCommand { |
| 37 const char* cmd_string; | 43 const char* cmd_string; |
| 38 CommandHandler handler_function; | 44 CommandHandler handler_function; |
| 39 }; | 45 }; |
| 40 | 46 |
| 41 | 47 |
| 42 class MessageBuffer { | 48 class MessageBuffer { |
| 43 public: | 49 public: |
| 44 explicit MessageBuffer(int fd); | 50 explicit MessageBuffer(int fd); |
| 45 ~MessageBuffer(); | 51 ~MessageBuffer(); |
| 46 void ReadData(); | 52 void ReadData(); |
| 47 bool IsValidMessage() const; | 53 bool IsValidMessage() const; |
| 48 void PopMessage(); | 54 void PopMessage(); |
| 49 int MessageId() const; | 55 int MessageId() const; |
| 50 const char* Params() const; | 56 const char* Params() const; |
| 57 intptr_t GetIntParam(const char* name) const; |
| 51 char* buf() const { return buf_; } | 58 char* buf() const { return buf_; } |
| 52 bool Alive() const { return connection_is_alive_; } | 59 bool Alive() const { return connection_is_alive_; } |
| 53 | 60 |
| 54 private: | 61 private: |
| 55 static const int kInitialBufferSize = 256; | 62 static const int kInitialBufferSize = 256; |
| 56 char* buf_; | 63 char* buf_; |
| 57 int buf_length_; | 64 int buf_length_; |
| 58 int fd_; | 65 int fd_; |
| 59 int data_length_; | 66 int data_length_; |
| 60 bool connection_is_alive_; | 67 bool connection_is_alive_; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 dart::JSONReader r(buf_); | 117 dart::JSONReader r(buf_); |
| 111 r.Seek("params"); | 118 r.Seek("params"); |
| 112 if (r.Type() == dart::JSONReader::kObject) { | 119 if (r.Type() == dart::JSONReader::kObject) { |
| 113 return r.ValueChars(); | 120 return r.ValueChars(); |
| 114 } else { | 121 } else { |
| 115 return NULL; | 122 return NULL; |
| 116 } | 123 } |
| 117 } | 124 } |
| 118 | 125 |
| 119 | 126 |
| 127 intptr_t MessageBuffer::GetIntParam(const char* name) const { |
| 128 const char* params = Params(); |
| 129 ASSERT(params != NULL); |
| 130 dart::JSONReader r(params); |
| 131 r.Seek(name); |
| 132 ASSERT(r.Type() == dart::JSONReader::kInteger); |
| 133 return strtol(r.ValueChars(), NULL, 10); |
| 134 } |
| 135 |
| 136 |
| 120 void MessageBuffer::ReadData() { | 137 void MessageBuffer::ReadData() { |
| 121 ASSERT(data_length_ >= 0); | 138 ASSERT(data_length_ >= 0); |
| 122 ASSERT(data_length_ < buf_length_); | 139 ASSERT(data_length_ < buf_length_); |
| 123 int max_read = buf_length_ - data_length_ - 1; | 140 int max_read = buf_length_ - data_length_ - 1; |
| 124 if (max_read == 0) { | 141 if (max_read == 0) { |
| 125 // TODO(hausner): | 142 // TODO(hausner): |
| 126 // Buffer is full. What should we do if there is no valid message | 143 // Buffer is full. What should we do if there is no valid message |
| 127 // in the buffer? This might be possible if the client sends a message | 144 // in the buffer? This might be possible if the client sends a message |
| 128 // that's larger than the buffer, of if the client sends malformed | 145 // that's larger than the buffer, of if the client sends malformed |
| 129 // messages that keep piling up. | 146 // messages that keep piling up. |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 ASSERT(Dart_IsString(lib_url)); | 290 ASSERT(Dart_IsString(lib_url)); |
| 274 char const* chars; | 291 char const* chars; |
| 275 Dart_StringToCString(lib_url, &chars); | 292 Dart_StringToCString(lib_url, &chars); |
| 276 msg.Printf("%s\"%s\"", (i == 0) ? "" : ", ", chars); | 293 msg.Printf("%s\"%s\"", (i == 0) ? "" : ", ", chars); |
| 277 } | 294 } |
| 278 msg.Printf("] }}"); | 295 msg.Printf("] }}"); |
| 279 SendMsg(&msg); | 296 SendMsg(&msg); |
| 280 } | 297 } |
| 281 | 298 |
| 282 | 299 |
| 300 static const char* GetStringChars(Dart_Handle str) { |
| 301 ASSERT(Dart_IsString(str)); |
| 302 const char* chars; |
| 303 Dart_Handle res = Dart_StringToCString(str, &chars); |
| 304 ASSERT(!Dart_IsError(res)); |
| 305 return chars; |
| 306 } |
| 307 |
| 308 |
| 309 static void FormatField(dart::TextBuffer* buf, |
| 310 Dart_Handle object_name, |
| 311 Dart_Handle object) { |
| 312 ASSERT(Dart_IsString(object_name)); |
| 313 buf->Printf("{\"name\":\"%s\",", GetStringChars(object_name)); |
| 314 intptr_t obj_id = Dart_CacheObject(object); |
| 315 ASSERT(obj_id >= 0); |
| 316 buf->Printf("\"value\":{\"objectId\":%d,", obj_id); |
| 317 const char* kind = "object"; |
| 318 if (Dart_IsInteger(object)) { |
| 319 kind = "integer"; |
| 320 } else if (Dart_IsString(object)) { |
| 321 kind = "string"; |
| 322 } else if (Dart_IsBoolean(object)) { |
| 323 kind = "boolean"; |
| 324 } |
| 325 buf->Printf("\"kind\":\"%s\",", kind); |
| 326 Dart_Handle text = Dart_ToString(object); |
| 327 buf->Printf("\"text\":\"%s\"}}", GetStringChars(text)); |
| 328 } |
| 329 |
| 330 |
| 331 static void FormatFieldList(dart::TextBuffer* buf, |
| 332 Dart_Handle obj_list) { |
| 333 ASSERT(Dart_IsList(obj_list)); |
| 334 intptr_t list_length = 0; |
| 335 Dart_Handle res = Dart_ListLength(obj_list, &list_length); |
| 336 ASSERT_NOT_ERROR(res); |
| 337 ASSERT(list_length % 2 == 0); |
| 338 buf->Printf("["); |
| 339 for (int i = 0; i + 1 < list_length; i += 2) { |
| 340 Dart_Handle name_handle = Dart_ListGetAt(obj_list, i); |
| 341 ASSERT_NOT_ERROR(name_handle); |
| 342 Dart_Handle value_handle = Dart_ListGetAt(obj_list, i + 1); |
| 343 ASSERT_NOT_ERROR(value_handle); |
| 344 if (i > 0) { |
| 345 buf->Printf(","); |
| 346 } |
| 347 FormatField(buf, name_handle, value_handle); |
| 348 } |
| 349 buf->Printf("]"); |
| 350 } |
| 351 |
| 352 |
| 353 static const char* FormatClassProps(dart::TextBuffer* buf, |
| 354 intptr_t cls_id) { |
| 355 Dart_Handle name, library, static_fields; |
| 356 intptr_t super_id; |
| 357 Dart_Handle res = |
| 358 Dart_GetClassInfo(cls_id, &name, &library, &super_id, &static_fields); |
| 359 RETURN_IF_ERROR(res); |
| 360 RETURN_IF_ERROR(name); |
| 361 buf->Printf("{\"name\":\"%s\",", GetStringChars(name)); |
| 362 if (super_id > 0) { |
| 363 buf->Printf("\"superclassId\":%d,", super_id); |
| 364 } |
| 365 RETURN_IF_ERROR(library); |
| 366 ASSERT(!Dart_IsNull(library)); |
| 367 // TODO(hausner): get proper library id. |
| 368 intptr_t libId = 0; |
| 369 buf->Printf("\"libraryId\":%d,", libId); |
| 370 RETURN_IF_ERROR(static_fields); |
| 371 buf->Printf("\"fields\":"); |
| 372 FormatFieldList(buf, static_fields); |
| 373 buf->Printf("}"); |
| 374 return NULL; |
| 375 } |
| 376 |
| 377 |
| 378 static const char* FormatObjProps(dart::TextBuffer* buf, |
| 379 Dart_Handle object) { |
| 380 intptr_t class_id; |
| 381 Dart_Handle res = Dart_GetObjClassId(object, &class_id); |
| 382 RETURN_IF_ERROR(res); |
| 383 buf->Printf("{\"classId\": %d, \"fields\":", class_id); |
| 384 Dart_Handle fields = Dart_GetInstanceFields(object); |
| 385 RETURN_IF_ERROR(fields); |
| 386 FormatFieldList(buf, fields); |
| 387 buf->Printf("}"); |
| 388 return NULL; |
| 389 } |
| 390 |
| 391 |
| 283 static void FormatCallFrames(dart::TextBuffer* msg, Dart_StackTrace trace) { | 392 static void FormatCallFrames(dart::TextBuffer* msg, Dart_StackTrace trace) { |
| 284 intptr_t trace_len = 0; | 393 intptr_t trace_len = 0; |
| 285 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len); | 394 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len); |
| 286 ASSERT_NOT_ERROR(res); | 395 ASSERT_NOT_ERROR(res); |
| 287 msg->Printf("\"callFrames\" : [ "); | 396 msg->Printf("\"callFrames\" : [ "); |
| 288 for (int i = 0; i < trace_len; i++) { | 397 for (int i = 0; i < trace_len; i++) { |
| 289 Dart_ActivationFrame frame; | 398 Dart_ActivationFrame frame; |
| 290 res = Dart_GetActivationFrame(trace, i, &frame); | 399 res = Dart_GetActivationFrame(trace, i, &frame); |
| 291 ASSERT_NOT_ERROR(res); | 400 ASSERT_NOT_ERROR(res); |
| 292 Dart_Handle func_name; | 401 Dart_Handle func_name; |
| 293 Dart_Handle script_url; | 402 Dart_Handle script_url; |
| 294 intptr_t line_number = 0; | 403 intptr_t line_number = 0; |
| 295 res = Dart_ActivationFrameInfo( | 404 res = Dart_ActivationFrameInfo( |
| 296 frame, &func_name, &script_url, &line_number); | 405 frame, &func_name, &script_url, &line_number); |
| 297 ASSERT_NOT_ERROR(res); | 406 ASSERT_NOT_ERROR(res); |
| 298 ASSERT(Dart_IsString(func_name)); | 407 ASSERT(Dart_IsString(func_name)); |
| 299 const char* func_name_chars; | 408 const char* func_name_chars; |
| 300 Dart_StringToCString(func_name, &func_name_chars); | 409 Dart_StringToCString(func_name, &func_name_chars); |
| 301 msg->Printf("%s { \"functionName\": \"%s\" , ", | 410 msg->Printf("%s { \"functionName\": \"%s\" , ", |
| 302 i > 0 ? "," : "", | 411 i > 0 ? "," : "", |
| 303 func_name_chars); | 412 func_name_chars); |
| 304 ASSERT(Dart_IsString(script_url)); | 413 ASSERT(Dart_IsString(script_url)); |
| 305 const char* script_url_chars; | 414 const char* script_url_chars; |
| 306 Dart_StringToCString(script_url, &script_url_chars); | 415 Dart_StringToCString(script_url, &script_url_chars); |
| 307 msg->Printf("\"location\": { \"url\": \"%s\", \"lineNumber\": %d }}", | 416 msg->Printf("\"location\": { \"url\": \"%s\", \"lineNumber\":%d},", |
| 308 script_url_chars, line_number); | 417 script_url_chars, line_number); |
| 418 Dart_Handle locals = Dart_GetLocalVariables(frame); |
| 419 ASSERT_NOT_ERROR(locals); |
| 420 msg->Printf("\"locals\":"); |
| 421 FormatFieldList(msg, locals); |
| 422 msg->Printf("}"); |
| 309 } | 423 } |
| 310 msg->Printf("]"); | 424 msg->Printf("]"); |
| 311 } | 425 } |
| 312 | 426 |
| 313 | 427 |
| 314 void DebuggerConnectionHandler::HandleGetStackTraceCmd(const char* json_msg) { | 428 void DebuggerConnectionHandler::HandleGetStackTraceCmd(const char* json_msg) { |
| 315 int msg_id = msgbuf_->MessageId(); | 429 int msg_id = msgbuf_->MessageId(); |
| 316 Dart_StackTrace trace; | 430 Dart_StackTrace trace; |
| 317 Dart_Handle res = Dart_GetStackTrace(&trace); | 431 Dart_Handle res = Dart_GetStackTrace(&trace); |
| 318 ASSERT_NOT_ERROR(res); | 432 ASSERT_NOT_ERROR(res); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 347 uint64_t bp_id_value; | 461 uint64_t bp_id_value; |
| 348 Dart_Handle res = Dart_IntegerToUint64(bp_id, &bp_id_value); | 462 Dart_Handle res = Dart_IntegerToUint64(bp_id, &bp_id_value); |
| 349 ASSERT_NOT_ERROR(res); | 463 ASSERT_NOT_ERROR(res); |
| 350 dart::TextBuffer msg(64); | 464 dart::TextBuffer msg(64); |
| 351 msg.Printf("{ \"id\": %d, \"result\": { \"breakpointId\": %d }}", | 465 msg.Printf("{ \"id\": %d, \"result\": { \"breakpointId\": %d }}", |
| 352 msg_id, bp_id_value); | 466 msg_id, bp_id_value); |
| 353 SendMsg(&msg); | 467 SendMsg(&msg); |
| 354 } | 468 } |
| 355 | 469 |
| 356 | 470 |
| 471 void DebuggerConnectionHandler::HandleGetObjPropsCmd(const char* json_msg) { |
| 472 int msg_id = msgbuf_->MessageId(); |
| 473 intptr_t obj_id = msgbuf_->GetIntParam("objectId"); |
| 474 Dart_Handle obj = Dart_GetCachedObject(obj_id); |
| 475 if (Dart_IsError(obj)) { |
| 476 SendError(msg_id, Dart_GetError(obj)); |
| 477 return; |
| 478 } |
| 479 dart::TextBuffer msg(64); |
| 480 msg.Printf("{\"id\":%d, \"result\":", msg_id); |
| 481 const char* err = FormatObjProps(&msg, obj); |
| 482 if (err != NULL) { |
| 483 SendError(msg_id, err); |
| 484 return; |
| 485 } |
| 486 msg.Printf("}"); |
| 487 SendMsg(&msg); |
| 488 } |
| 489 |
| 490 |
| 491 void DebuggerConnectionHandler::HandleGetClassPropsCmd(const char* json_msg) { |
| 492 int msg_id = msgbuf_->MessageId(); |
| 493 intptr_t cls_id = msgbuf_->GetIntParam("classId"); |
| 494 dart::TextBuffer msg(64); |
| 495 msg.Printf("{\"id\":%d, \"result\":", msg_id); |
| 496 const char* err = FormatClassProps(&msg, cls_id); |
| 497 if (err != NULL) { |
| 498 SendError(msg_id, err); |
| 499 return; |
| 500 } |
| 501 msg.Printf("}"); |
| 502 SendMsg(&msg); |
| 503 } |
| 504 |
| 505 |
| 357 void DebuggerConnectionHandler::HandleUnknownMsg(const char* json_msg) { | 506 void DebuggerConnectionHandler::HandleUnknownMsg(const char* json_msg) { |
| 358 int msg_id = msgbuf_->MessageId(); | 507 int msg_id = msgbuf_->MessageId(); |
| 359 ASSERT(msg_id >= 0); | 508 ASSERT(msg_id >= 0); |
| 360 SendError(msg_id, "unknown debugger command"); | 509 SendError(msg_id, "unknown debugger command"); |
| 361 } | 510 } |
| 362 | 511 |
| 363 | 512 |
| 364 void DebuggerConnectionHandler::HandleMessages() { | 513 void DebuggerConnectionHandler::HandleMessages() { |
| 365 static JSONDebuggerCommand debugger_commands[] = { | 514 static JSONDebuggerCommand debugger_commands[] = { |
| 366 { "resume", HandleResumeCmd }, | 515 { "resume", HandleResumeCmd }, |
| 367 { "getLibraryURLs", HandleGetLibraryURLsCmd}, | 516 { "getLibraryURLs", HandleGetLibraryURLsCmd }, |
| 517 { "getClassProperties", HandleGetClassPropsCmd }, |
| 518 { "getObjectProperties", HandleGetObjPropsCmd }, |
| 368 { "getScriptURLs", HandleGetScriptURLsCmd }, | 519 { "getScriptURLs", HandleGetScriptURLsCmd }, |
| 369 { "getStackTrace", HandleGetStackTraceCmd }, | 520 { "getStackTrace", HandleGetStackTraceCmd }, |
| 370 { "setBreakpoint", HandleSetBpCmd }, | 521 { "setBreakpoint", HandleSetBpCmd }, |
| 371 { "stepInto", HandleStepIntoCmd }, | 522 { "stepInto", HandleStepIntoCmd }, |
| 372 { "stepOut", HandleStepOutCmd }, | 523 { "stepOut", HandleStepOutCmd }, |
| 373 { "stepOver", HandleStepOverCmd }, | 524 { "stepOver", HandleStepOverCmd }, |
| 374 { NULL, NULL } | 525 { NULL, NULL } |
| 375 }; | 526 }; |
| 376 | 527 |
| 377 for (;;) { | 528 for (;;) { |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 handler_started_ = true; | 649 handler_started_ = true; |
| 499 DebuggerConnectionImpl::StartHandler(port_number); | 650 DebuggerConnectionImpl::StartHandler(port_number); |
| 500 Dart_SetBreakpointHandler(BreakpointHandler); | 651 Dart_SetBreakpointHandler(BreakpointHandler); |
| 501 Dart_SetBreakpointResolvedHandler(BptResolvedHandler); | 652 Dart_SetBreakpointResolvedHandler(BptResolvedHandler); |
| 502 } | 653 } |
| 503 | 654 |
| 504 | 655 |
| 505 DebuggerConnectionHandler::~DebuggerConnectionHandler() { | 656 DebuggerConnectionHandler::~DebuggerConnectionHandler() { |
| 506 CloseDbgConnection(); | 657 CloseDbgConnection(); |
| 507 } | 658 } |
| OLD | NEW |