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

Unified Diff: runtime/bin/dbg_message.cc

Issue 10990089: First step towards support for being able to interrupt a running Dart Isolate (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 side-by-side diff with in-line comments
Download patch
« runtime/bin/dbg_message.h ('K') | « runtime/bin/dbg_message.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/dbg_message.cc
===================================================================
--- runtime/bin/dbg_message.cc (revision 0)
+++ runtime/bin/dbg_message.cc (revision 0)
@@ -0,0 +1,941 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "bin/dbg_connection.h"
+#include "bin/dbg_message.h"
+#include "bin/dartutils.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+
+#include "platform/globals.h"
+#include "platform/json.h"
+#include "platform/thread.h"
+#include "platform/utils.h"
+
+#include "include/dart_api.h"
+
+bool MessageParser::IsValidMessage() const {
+ if (buf_length_ == 0) {
+ return false;
+ }
+ dart::JSONReader msg_reader(buf_);
+ return msg_reader.EndOfObject() != NULL;
+}
+
+
+int MessageParser::MessageId() const {
+ dart::JSONReader r(buf_);
+ r.Seek("id");
+ if (r.Type() == dart::JSONReader::kInteger) {
+ return atoi(r.ValueChars());
+ } else {
+ return -1;
+ }
+}
+
+
+const char* MessageParser::Params() const {
+ dart::JSONReader r(buf_);
+ r.Seek("params");
+ if (r.Type() == dart::JSONReader::kObject) {
+ return r.ValueChars();
+ } else {
+ return NULL;
+ }
+}
+
+
+intptr_t MessageParser::GetIntParam(const char* name) const {
+ const char* params = Params();
+ ASSERT(params != NULL);
+ dart::JSONReader r(params);
+ r.Seek(name);
+ ASSERT(r.Type() == dart::JSONReader::kInteger);
+ return strtol(r.ValueChars(), NULL, 10);
+}
+
+
+intptr_t MessageParser::GetOptIntParam(const char* name,
+ intptr_t default_val) const {
+ const char* params = Params();
+ ASSERT(params != NULL);
+ dart::JSONReader r(params);
+ r.Seek(name);
+ if (r.Type() == dart::JSONReader::kInteger) {
+ return strtol(r.ValueChars(), NULL, 10);
+ } else {
+ return default_val;
+ }
+}
+
+
+static const char* GetStringChars(Dart_Handle str) {
+ ASSERT(Dart_IsString(str));
+ const char* chars;
+ Dart_Handle res = Dart_StringToCString(str, &chars);
+ ASSERT(!Dart_IsError(res));
+ return chars;
+}
+
+
+static int GetIntValue(Dart_Handle int_handle) {
+ int64_t int64_val = -1;
+ ASSERT(Dart_IsInteger(int_handle));
+ Dart_Handle res = Dart_IntegerToInt64(int_handle, &int64_val);
+ ASSERT_NOT_ERROR(res);
+ // TODO(hausner): Range check.
+ return int64_val;
+}
+
+
+char* MessageParser::GetStringParam(const char* name) const {
+ const char* params = Params();
+ ASSERT(params != NULL);
+ dart::JSONReader pr(params);
+ pr.Seek(name);
+ if (pr.Type() != dart::JSONReader::kString) {
+ return NULL;
+ }
+ intptr_t buflen = pr.ValueLen() + 1;
+ char* param_chars = reinterpret_cast<char*>(malloc(buflen));
+ pr.GetValueChars(param_chars, buflen);
+ // TODO(hausner): Decode escape sequences.
+ return param_chars;
+}
+
+
+static void FormatEncodedString(dart::TextBuffer* buf, Dart_Handle str) {
+ intptr_t str_len = 0;
+ Dart_Handle res = Dart_StringLength(str, &str_len);
+ ASSERT_NOT_ERROR(res);
+ uint32_t* codepoints =
+ reinterpret_cast<uint32_t*>(malloc(str_len * sizeof(uint32_t)));
+ ASSERT(codepoints != NULL);
+ intptr_t actual_len = str_len;
+ res = Dart_StringGet32(str, codepoints, &actual_len);
+ ASSERT_NOT_ERROR(res);
+ ASSERT(str_len == actual_len);
+ buf->AddChar('\"');
+ for (int i = 0; i < str_len; i++) {
+ buf->AddEscapedChar(codepoints[i]);
+ }
+ buf->AddChar('\"');
+ free(codepoints);
+}
+
+
+static void FormatErrorMsg(dart::TextBuffer* buf, Dart_Handle err) {
+ // TODO(hausner): Turn message into Dart string and
+ // properly encode the message.
+ ASSERT(Dart_IsError(err));
+ const char* msg = Dart_GetError(err);
+ buf->Printf("\"%s\"", msg);
+}
+
+
+static void FormatTextualValue(dart::TextBuffer* buf, Dart_Handle object) {
+ Dart_Handle text;
+ if (Dart_IsNull(object)) {
+ text = Dart_Null();
+ } else {
+ Dart_ExceptionPauseInfo savedState = Dart_GetExceptionPauseInfo();
+
+ // TODO(hausner): Check whether recursive/reentrant pauses on exceptions
+ // should be prevented in Debugger::SignalExceptionThrown() instead.
+ if (savedState != kNoPauseOnExceptions) {
+ Dart_Handle res = Dart_SetExceptionPauseInfo(kNoPauseOnExceptions);
+ ASSERT_NOT_ERROR(res);
+ }
+
+ text = Dart_ToString(object);
+
+ if (savedState != kNoPauseOnExceptions) {
+ Dart_Handle res = Dart_SetExceptionPauseInfo(savedState);
+ ASSERT_NOT_ERROR(res);
+ }
+ }
+ buf->Printf("\"text\":");
+ if (Dart_IsNull(text)) {
+ buf->Printf("null");
+ } else if (Dart_IsError(text)) {
+ FormatErrorMsg(buf, text);
+ } else {
+ FormatEncodedString(buf, text);
+ }
+}
+
+
+static void FormatValue(dart::TextBuffer* buf, Dart_Handle object) {
+ if (Dart_IsInteger(object)) {
+ buf->Printf("\"kind\":\"integer\",");
+ } else if (Dart_IsString(object)) {
+ buf->Printf("\"kind\":\"string\",");
+ } else if (Dart_IsBoolean(object)) {
+ buf->Printf("\"kind\":\"boolean\",");
+ } else if (Dart_IsList(object)) {
+ intptr_t len = 0;
+ Dart_Handle res = Dart_ListLength(object, &len);
+ ASSERT_NOT_ERROR(res);
+ buf->Printf("\"kind\":\"list\",\"length\":%"Pd",", len);
+ } else {
+ buf->Printf("\"kind\":\"object\",");
+ }
+ FormatTextualValue(buf, object);
+}
+
+
+static void FormatValueObj(dart::TextBuffer* buf, Dart_Handle object) {
+ buf->Printf("{");
+ FormatValue(buf, object);
+ buf->Printf("}");
+}
+
+
+static void FormatRemoteObj(dart::TextBuffer* buf, Dart_Handle object) {
+ intptr_t obj_id = Dart_CacheObject(object);
+ ASSERT(obj_id >= 0);
+ buf->Printf("{\"objectId\":%"Pd",", obj_id);
+ FormatValue(buf, object);
+ buf->Printf("}");
+}
+
+
+static void FormatNamedValue(dart::TextBuffer* buf,
+ Dart_Handle object_name,
+ Dart_Handle object) {
+ ASSERT(Dart_IsString(object_name));
+ buf->Printf("{\"name\":\"%s\",", GetStringChars(object_name));
+ buf->Printf("\"value\":");
+ FormatRemoteObj(buf, object);
+ buf->Printf("}");
+}
+
+
+static void FormatNamedValueList(dart::TextBuffer* buf,
+ Dart_Handle obj_list) {
+ ASSERT(Dart_IsList(obj_list));
+ intptr_t list_length = 0;
+ Dart_Handle res = Dart_ListLength(obj_list, &list_length);
+ ASSERT_NOT_ERROR(res);
+ ASSERT(list_length % 2 == 0);
+ buf->Printf("[");
+ for (int i = 0; i + 1 < list_length; i += 2) {
+ Dart_Handle name_handle = Dart_ListGetAt(obj_list, i);
+ ASSERT_NOT_ERROR(name_handle);
+ Dart_Handle value_handle = Dart_ListGetAt(obj_list, i + 1);
+ ASSERT_NOT_ERROR(value_handle);
+ if (i > 0) {
+ buf->Printf(",");
+ }
+ FormatNamedValue(buf, name_handle, value_handle);
+ }
+ buf->Printf("]");
+}
+
+
+static const char* FormatClassProps(dart::TextBuffer* buf,
+ intptr_t cls_id) {
+ Dart_Handle name, static_fields;
+ intptr_t super_id = -1;
+ intptr_t library_id = -1;
+ Dart_Handle res =
+ Dart_GetClassInfo(cls_id, &name, &library_id, &super_id, &static_fields);
+ RETURN_IF_ERROR(res);
+ RETURN_IF_ERROR(name);
+ buf->Printf("{\"name\":\"%s\",", GetStringChars(name));
+ if (super_id > 0) {
+ buf->Printf("\"superclassId\":%"Pd",", super_id);
+ }
+ buf->Printf("\"libraryId\":%"Pd",", library_id);
+ RETURN_IF_ERROR(static_fields);
+ buf->Printf("\"fields\":");
+ FormatNamedValueList(buf, static_fields);
+ buf->Printf("}");
+ return NULL;
+}
+
+
+static const char* FormatLibraryProps(dart::TextBuffer* buf,
+ intptr_t lib_id) {
+ Dart_Handle url = Dart_GetLibraryURL(lib_id);
+ RETURN_IF_ERROR(url);
+ buf->Printf("{\"url\":");
+ FormatEncodedString(buf, url);
+
+ // Whether debugging is enabled.
+ bool is_debuggable = false;
+ Dart_Handle res = Dart_GetLibraryDebuggable(lib_id, &is_debuggable);
+ RETURN_IF_ERROR(res);
+ buf->Printf(",\"debuggingEnabled\":%s",
+ is_debuggable ? "\"true\"" : "\"false\"");
+
+ // Imports and prefixes.
+ Dart_Handle import_list = Dart_GetLibraryImports(lib_id);
+ RETURN_IF_ERROR(import_list);
+ ASSERT(Dart_IsList(import_list));
+ intptr_t list_length = 0;
+ res = Dart_ListLength(import_list, &list_length);
+ RETURN_IF_ERROR(res);
+ buf->Printf(",\"imports\":[");
+ for (int i = 0; i + 1 < list_length; i += 2) {
+ Dart_Handle lib_id = Dart_ListGetAt(import_list, i + 1);
+ ASSERT_NOT_ERROR(lib_id);
+ buf->Printf("%s{\"libraryId\":%d,",
+ (i > 0) ? ",": "",
+ GetIntValue(lib_id));
+
+ Dart_Handle name = Dart_ListGetAt(import_list, i);
+ ASSERT_NOT_ERROR(name);
+ buf->Printf("\"prefix\":\"%s\"}",
+ Dart_IsNull(name) ? "" : GetStringChars(name));
+ }
+ buf->Printf("],");
+
+ // Global variables in the library.
+ Dart_Handle global_vars = Dart_GetLibraryFields(lib_id);
+ RETURN_IF_ERROR(global_vars);
+ buf->Printf("\"globals\":");
+ FormatNamedValueList(buf, global_vars);
+ buf->Printf("}");
+ return NULL;
+}
+
+
+static const char* FormatObjProps(dart::TextBuffer* buf,
+ Dart_Handle object) {
+ intptr_t class_id;
+ if (Dart_IsNull(object)) {
+ buf->Printf("{\"classId\":-1,\"fields\":[]}");
+ return NULL;
+ }
+ Dart_Handle res = Dart_GetObjClassId(object, &class_id);
+ RETURN_IF_ERROR(res);
+ buf->Printf("{\"classId\": %"Pd",", class_id);
+ buf->Printf("\"kind\":\"object\",\"fields\":");
+ Dart_Handle fields = Dart_GetInstanceFields(object);
+ RETURN_IF_ERROR(fields);
+ FormatNamedValueList(buf, fields);
+ buf->Printf("}");
+ return NULL;
+}
+
+
+static const char* FormatListSlice(dart::TextBuffer* buf,
+ Dart_Handle list,
+ intptr_t list_length,
+ intptr_t index,
+ intptr_t slice_length) {
+ intptr_t end_index = index + slice_length;
+ ASSERT(end_index <= list_length);
+ buf->Printf("{\"index\":%"Pd",", index);
+ buf->Printf("\"length\":%"Pd",", slice_length);
+ buf->Printf("\"elements\":[");
+ for (intptr_t i = index; i < end_index; i++) {
+ Dart_Handle value = Dart_ListGetAt(list, i);
+ if (i > index) {
+ buf->Printf(",");
+ }
+ FormatValueObj(buf, value);
+ }
+ buf->Printf("]}");
+ return NULL;
+}
+
+
+static void FormatCallFrames(dart::TextBuffer* msg, Dart_StackTrace trace) {
+ intptr_t trace_len = 0;
+ Dart_Handle res = Dart_StackTraceLength(trace, &trace_len);
+ ASSERT_NOT_ERROR(res);
+ msg->Printf("\"callFrames\" : [ ");
+ for (int i = 0; i < trace_len; i++) {
+ Dart_ActivationFrame frame;
+ res = Dart_GetActivationFrame(trace, i, &frame);
+ ASSERT_NOT_ERROR(res);
+ Dart_Handle func_name;
+ Dart_Handle script_url;
+ intptr_t line_number = 0;
+ intptr_t library_id = 0;
+ res = Dart_ActivationFrameInfo(
+ frame, &func_name, &script_url, &line_number, &library_id);
+ ASSERT_NOT_ERROR(res);
+ ASSERT(Dart_IsString(func_name));
+ msg->Printf("%s{\"functionName\":", (i > 0) ? "," : "");
+ FormatEncodedString(msg, func_name);
+ msg->Printf(",\"libraryId\": %"Pd",", library_id);
+
+ ASSERT(Dart_IsString(script_url));
+ msg->Printf("\"location\": { \"url\":");
+ FormatEncodedString(msg, script_url);
+ msg->Printf(",\"lineNumber\":%"Pd"},", line_number);
+
+ Dart_Handle locals = Dart_GetLocalVariables(frame);
+ ASSERT_NOT_ERROR(locals);
+ msg->Printf("\"locals\":");
+ FormatNamedValueList(msg, locals);
+ msg->Printf("}");
+ }
+ msg->Printf("]");
+}
+
+
+typedef void (*CommandHandler)(DbgMessage* msg);
+
+struct JSONDebuggerCommand {
+ const char* cmd_string;
+ CommandHandler handler_function;
+};
+
+
+static JSONDebuggerCommand debugger_commands[] = {
+ { "resume", DbgMessage::HandleResumeCmd },
+ { "stepInto", DbgMessage::HandleStepIntoCmd },
+ { "stepOut", DbgMessage::HandleStepOutCmd },
+ { "stepOver", DbgMessage::HandleStepOverCmd },
+ { "getLibraries", DbgMessage::HandleGetLibrariesCmd },
+ { "getClassProperties", DbgMessage::HandleGetClassPropsCmd },
+ { "getLibraryProperties", DbgMessage::HandleGetLibPropsCmd },
+ { "setLibraryProperties", DbgMessage::HandleSetLibPropsCmd },
+ { "getObjectProperties", DbgMessage::HandleGetObjPropsCmd },
+ { "getListElements", DbgMessage::HandleGetListCmd },
+ { "getGlobalVariables", DbgMessage::HandleGetGlobalsCmd },
+ { "getScriptURLs", DbgMessage::HandleGetScriptURLsCmd },
+ { "getScriptSource", DbgMessage::HandleGetSourceCmd },
+ { "getStackTrace", DbgMessage::HandleGetStackTraceCmd },
+ { "setBreakpoint", DbgMessage::HandleSetBpCmd },
+ { "setPauseOnException", DbgMessage::HandlePauseOnExcCmd },
+ { "removeBreakpoint", DbgMessage::HandleRemBpCmd },
+ { NULL, NULL }
+};
+
+
+void DbgMessage::HandleMessage() {
+ // Dispatch to the appropriate handler for the command.
+ int max_index = (sizeof(debugger_commands) / sizeof(JSONDebuggerCommand));
+ ASSERT(cmd_idx_ < max_index);
+ (*debugger_commands[cmd_idx_].handler_function)(this);
+}
+
+
+void DbgMessage::SendReply(dart::TextBuffer* reply) {
+ DebuggerConnectionHandler::SendMsg(debug_fd(), reply);
+}
+
+
+void DbgMessage::SendErrorReply(int msg_id, const char* err_msg) {
+ DebuggerConnectionHandler::SendError(debug_fd(), msg_id, err_msg);
+}
+
+
+void DbgMessage::HandleResumeCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ dart::TextBuffer msg(64);
+ msg.Printf("{ \"id\": %d }", msg_id);
+ in_msg->SendReply(&msg);
+ in_msg->set_request_resume(true);
+}
+
+
+void DbgMessage::HandleStepIntoCmd(DbgMessage* in_msg) {
+ Dart_Handle res = Dart_SetStepInto();
+ ASSERT_NOT_ERROR(res);
+ HandleResumeCmd(in_msg);
+}
+
+
+void DbgMessage::HandleStepOutCmd(DbgMessage* in_msg) {
+ Dart_Handle res = Dart_SetStepOut();
+ ASSERT_NOT_ERROR(res);
+ HandleResumeCmd(in_msg);
+}
+
+
+void DbgMessage::HandleStepOverCmd(DbgMessage* in_msg) {
+ Dart_Handle res = Dart_SetStepOver();
+ ASSERT_NOT_ERROR(res);
+ HandleResumeCmd(in_msg);
+}
+
+
+void DbgMessage::HandleGetLibrariesCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ dart::TextBuffer msg(64);
+ msg.Printf("{ \"id\": %d, \"result\": { \"libraries\": [", msg_id);
+ Dart_Handle lib_ids = Dart_GetLibraryIds();
+ ASSERT_NOT_ERROR(lib_ids);
+ intptr_t num_libs;
+ Dart_Handle res = Dart_ListLength(lib_ids, &num_libs);
+ ASSERT_NOT_ERROR(res);
+ for (int i = 0; i < num_libs; i++) {
+ Dart_Handle lib_id_handle = Dart_ListGetAt(lib_ids, i);
+ ASSERT(Dart_IsInteger(lib_id_handle));
+ int lib_id = GetIntValue(lib_id_handle);
+ Dart_Handle lib_url = Dart_GetLibraryURL(lib_id);
+ ASSERT_NOT_ERROR(lib_url);
+ ASSERT(Dart_IsString(lib_url));
+ msg.Printf("%s{\"id\":%d,\"url\":", (i == 0) ? "" : ", ", lib_id);
+ FormatEncodedString(&msg, lib_url);
+ msg.Printf("}");
+ }
+ msg.Printf("]}}");
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleGetClassPropsCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ intptr_t cls_id = msg_parser.GetIntParam("classId");
+ dart::TextBuffer msg(64);
+ msg.Printf("{\"id\":%d, \"result\":", msg_id);
+ const char* err = FormatClassProps(&msg, cls_id);
+ if (err != NULL) {
+ in_msg->SendErrorReply(msg_id, err);
+ return;
+ }
+ msg.Printf("}");
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleGetLibPropsCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ intptr_t lib_id = msg_parser.GetIntParam("libraryId");
+ dart::TextBuffer msg(64);
+ msg.Printf("{\"id\":%d, \"result\":", msg_id);
+ const char* err = FormatLibraryProps(&msg, lib_id);
+ if (err != NULL) {
+ in_msg->SendErrorReply(msg_id, err);
+ return;
+ }
+ msg.Printf("}");
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleSetLibPropsCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ intptr_t lib_id = msg_parser.GetIntParam("libraryId");
+ const char* enable_request = msg_parser.GetStringParam("debuggingEnabled");
+ bool enable;
+ if (strcmp(enable_request, "true") == 0) {
+ enable = true;
+ } else if (strcmp(enable_request, "false") == 0) {
+ enable = false;
+ } else {
+ in_msg->SendErrorReply(msg_id, "illegal argument for 'debuggingEnabled'");
+ return;
+ }
+ Dart_Handle res = Dart_SetLibraryDebuggable(lib_id, enable);
+ if (Dart_IsError(res)) {
+ in_msg->SendErrorReply(msg_id, Dart_GetError(res));
+ return;
+ }
+ bool enabled = false;
+ res = Dart_GetLibraryDebuggable(lib_id, &enabled);
+ if (Dart_IsError(res)) {
+ in_msg->SendErrorReply(msg_id, Dart_GetError(res));
+ return;
+ }
+ dart::TextBuffer msg(64);
+ msg.Printf("{\"id\":%d, \"result\": {\"debuggingEnabled\": \"%s\"}}",
+ msg_id,
+ enabled ? "true" : "false");
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleGetObjPropsCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ intptr_t obj_id = msg_parser.GetIntParam("objectId");
+ Dart_Handle obj = Dart_GetCachedObject(obj_id);
+ if (Dart_IsError(obj)) {
+ in_msg->SendErrorReply(msg_id, Dart_GetError(obj));
+ return;
+ }
+ dart::TextBuffer msg(64);
+ msg.Printf("{\"id\":%d, \"result\":", msg_id);
+ const char* err = FormatObjProps(&msg, obj);
+ if (err != NULL) {
+ in_msg->SendErrorReply(msg_id, err);
+ return;
+ }
+ msg.Printf("}");
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleGetListCmd(DbgMessage* in_msg) {
+ const intptr_t kDefaultSliceLength = 100;
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ intptr_t obj_id = msg_parser.GetIntParam("objectId");
+ Dart_Handle list = Dart_GetCachedObject(obj_id);
+ if (Dart_IsError(list)) {
+ in_msg->SendErrorReply(msg_id, Dart_GetError(list));
+ return;
+ }
+ if (!Dart_IsList(list)) {
+ in_msg->SendErrorReply(msg_id, "object is not a list");
+ return;
+ }
+ intptr_t list_length = 0;
+ Dart_Handle res = Dart_ListLength(list, &list_length);
+ if (Dart_IsError(res)) {
+ in_msg->SendErrorReply(msg_id, Dart_GetError(res));
+ return;
+ }
+
+ intptr_t index = msg_parser.GetIntParam("index");
+ if (index < 0) {
+ index = 0;
+ } else if (index > list_length) {
+ index = list_length;
+ }
+
+ // If no slice length is given, get only one element. If slice length
+ // is given as 0, get entire list.
+ intptr_t slice_length = msg_parser.GetOptIntParam("length", 1);
+ if (slice_length == 0) {
+ slice_length = list_length - index;
+ }
+ if ((index + slice_length) > list_length) {
+ slice_length = list_length - index;
+ }
+ ASSERT(slice_length >= 0);
+ if (slice_length > kDefaultSliceLength) {
+ slice_length = kDefaultSliceLength;
+ }
+ dart::TextBuffer msg(64);
+ msg.Printf("{\"id\":%d, \"result\":", msg_id);
+ if (slice_length == 1) {
+ Dart_Handle value = Dart_ListGetAt(list, index);
+ FormatRemoteObj(&msg, value);
+ } else {
+ FormatListSlice(&msg, list, list_length, index, slice_length);
+ }
+ msg.Printf("}");
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleGetGlobalsCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ intptr_t lib_id = msg_parser.GetIntParam("libraryId");
+ dart::TextBuffer msg(64);
+ msg.Printf("{\"id\":%d, \"result\": { \"globals\":", msg_id);
+ Dart_Handle globals = Dart_GetGlobalVariables(lib_id);
+ ASSERT_NOT_ERROR(globals);
+ FormatNamedValueList(&msg, globals);
+ msg.Printf("}}");
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleGetScriptURLsCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ dart::TextBuffer msg(64);
+ intptr_t lib_id = msg_parser.GetIntParam("libraryId");
+ Dart_Handle lib_url = Dart_GetLibraryURL(lib_id);
+ ASSERT_NOT_ERROR(lib_url);
+ Dart_Handle urls = Dart_GetScriptURLs(lib_url);
+ if (Dart_IsError(urls)) {
+ in_msg->SendErrorReply(msg_id, Dart_GetError(urls));
+ return;
+ }
+ ASSERT(Dart_IsList(urls));
+ intptr_t num_urls = 0;
+ Dart_ListLength(urls, &num_urls);
+ msg.Printf("{ \"id\": %d, ", msg_id);
+ msg.Printf("\"result\": { \"urls\": [");
+ for (int i = 0; i < num_urls; i++) {
+ Dart_Handle script_url = Dart_ListGetAt(urls, i);
+ if (i > 0) {
+ msg.Printf(",");
+ }
+ FormatEncodedString(&msg, script_url);
+ }
+ msg.Printf("]}}");
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleGetSourceCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ dart::TextBuffer msg(64);
+ intptr_t lib_id = msg_parser.GetIntParam("libraryId");
+ char* url_chars = msg_parser.GetStringParam("url");
+ ASSERT(url_chars != NULL);
+ Dart_Handle url = Dart_NewString(url_chars);
+ ASSERT_NOT_ERROR(url);
+ free(url_chars);
+ url_chars = NULL;
+ Dart_Handle source = Dart_ScriptGetSource(lib_id, url);
+ if (Dart_IsError(source)) {
+ in_msg->SendErrorReply(msg_id, Dart_GetError(source));
+ return;
+ }
+ msg.Printf("{ \"id\": %d, ", msg_id);
+ msg.Printf("\"result\": { \"text\": ");
+ FormatEncodedString(&msg, source);
+ msg.Printf("}}");
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleGetStackTraceCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ Dart_StackTrace trace;
+ Dart_Handle res = Dart_GetStackTrace(&trace);
+ ASSERT_NOT_ERROR(res);
+ dart::TextBuffer msg(128);
+ msg.Printf("{ \"id\": %d, \"result\": {", msg_id);
+ FormatCallFrames(&msg, trace);
+ msg.Printf("}}");
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleSetBpCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ char* url_chars = msg_parser.GetStringParam("url");
+ ASSERT(url_chars != NULL);
+ Dart_Handle url = Dart_NewString(url_chars);
+ ASSERT_NOT_ERROR(url);
+ free(url_chars);
+ url_chars = NULL;
+ intptr_t line_number = msg_parser.GetIntParam("line");
+ Dart_Handle bp_id = Dart_SetBreakpoint(url, line_number);
+ if (Dart_IsError(bp_id)) {
+ in_msg->SendErrorReply(msg_id, Dart_GetError(bp_id));
+ return;
+ }
+ ASSERT(Dart_IsInteger(bp_id));
+ uint64_t bp_id_value;
+ Dart_Handle res = Dart_IntegerToUint64(bp_id, &bp_id_value);
+ ASSERT_NOT_ERROR(res);
+ dart::TextBuffer msg(64);
+ msg.Printf("{ \"id\": %d, \"result\": { \"breakpointId\": %"Pu64" }}",
+ msg_id, bp_id_value);
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandlePauseOnExcCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ char* exc_chars = msg_parser.GetStringParam("exceptions");
+ Dart_ExceptionPauseInfo info = kNoPauseOnExceptions;
+ if (strcmp(exc_chars, "none") == 0) {
+ info = kNoPauseOnExceptions;
+ } else if (strcmp(exc_chars, "all") == 0) {
+ info = kPauseOnAllExceptions;
+ } else if (strcmp(exc_chars, "unhandled") == 0) {
+ info = kPauseOnUnhandledExceptions;
+ } else {
+ in_msg->SendErrorReply(msg_id, "illegal value for parameter 'exceptions'");
+ return;
+ }
+ Dart_Handle res = Dart_SetExceptionPauseInfo(info);
+ ASSERT_NOT_ERROR(res);
+ dart::TextBuffer msg(32);
+ msg.Printf("{ \"id\": %d }", msg_id);
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessage::HandleRemBpCmd(DbgMessage* in_msg) {
+ ASSERT(in_msg != NULL);
+ MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
+ int msg_id = msg_parser.MessageId();
+ int bpt_id = msg_parser.GetIntParam("breakpointId");
+ Dart_Handle res = Dart_RemoveBreakpoint(bpt_id);
+ if (Dart_IsError(res)) {
+ in_msg->SendErrorReply(msg_id, Dart_GetError(res));
+ return;
+ }
+ dart::TextBuffer msg(32);
+ msg.Printf("{ \"id\": %d }", msg_id);
+ in_msg->SendReply(&msg);
+}
+
+
+void DbgMessageQueue::AddMessage(int32_t cmd_idx,
+ const char* start,
+ const char* end,
+ int debug_fd) {
+ if ((end > start) && ((end - start) < kMaxUint32)) {
+ MonitorLocker ml(&msg_queue_lock_);
+ bool notify = (msglist_ == NULL);
+ DbgMessage* msg = new DbgMessage(msglist_, cmd_idx, start, end, debug_fd);
+ msglist_ = msg;
hausner 2012/09/28 17:03:01 It seems that you are inserting the message at the
siva 2012/09/28 23:32:29 Very good point. That was not intentional... Chang
+ if (notify) {
+ ml.Notify();
+ }
+ }
+}
+
+
+void DbgMessageQueue::HandleMessages() {
+ bool resume_requested = false;
+ MonitorLocker ml(&msg_queue_lock_);
+ is_running_ = false;
+ while (!resume_requested) {
+ while (msglist_ == NULL) {
+ dart::Monitor::WaitResult res = ml.Wait(); // Wait for debugger commands.
+ ASSERT(res == dart::Monitor::kNotified);
+ }
+ while (msglist_ != NULL) {
+ DbgMessage* msg = msglist_;
+ msglist_ = msglist_->next();
+ msg->HandleMessage();
+ resume_requested = msg->request_resume();
hausner 2012/09/28 17:03:01 This is the only place where you need to know whet
siva 2012/09/28 23:32:29 HandleMessage() now returns true to indicate a res
+ delete msg;
+ }
+ }
+ is_running_ = true;
+}
+
+
+void DbgMessageQueue::QueueOutputMsg(dart::TextBuffer* msg) {
+ queued_output_messages_.Printf("%s", msg->buf());
+}
+
+
+void DbgMessageQueue::SendQueuedMsgs() {
+ if (queued_output_messages_.length() > 0) {
+ DebuggerConnectionHandler::BroadcastMsg(&queued_output_messages_);
+ queued_output_messages_.Clear();
+ }
+}
+
+
+void DbgMessageQueue::SendBreakpointEvent(Dart_StackTrace trace) {
+ dart::TextBuffer msg(128);
+ msg.Printf("{ \"event\": \"paused\", \"params\": { ");
+ msg.Printf("\"reason\": \"breakpoint\", ");
+ FormatCallFrames(&msg, trace);
+ msg.Printf("}}");
+ DebuggerConnectionHandler::BroadcastMsg(&msg);
+}
+
+
+void DbgMessageQueue::SendExceptionEvent(Dart_Handle exception,
+ Dart_StackTrace stack_trace) {
+ intptr_t exception_id = Dart_CacheObject(exception);
+ ASSERT(exception_id >= 0);
+ dart::TextBuffer msg(128);
+ msg.Printf("{ \"event\": \"paused\", \"params\": {");
+ msg.Printf("\"reason\": \"exception\", ");
+ msg.Printf("\"exception\":");
+ FormatRemoteObj(&msg, exception);
+ msg.Printf(", ");
+ FormatCallFrames(&msg, stack_trace);
+ msg.Printf("}}");
+ DebuggerConnectionHandler::BroadcastMsg(&msg);
+}
+
+
+// TODO(asiva): Get rid of this statis variabel one we have a means
hausner 2012/09/28 17:03:01 static variable
siva 2012/09/28 23:32:29 Done.
+// for associating an isolate with a debugger message queue object.
+static DbgMessageQueue* message_queue = NULL;
+
+
+void DbgMessageQueue::Initialize() {
+ // TODO(asiva): Need to setup a message queue when an Isolate is created.
+ // For now we use a static message queue object as we are only supporting
+ // debugging of a single isolate.
+ message_queue = new DbgMessageQueue();
+
+ // Setup handlers for breakpoints, exceptions and delayed breakpoints.
+ Dart_SetBreakpointHandler(BreakpointHandler);
+ Dart_SetBreakpointResolvedHandler(BptResolvedHandler);
+ Dart_SetExceptionThrownHandler(ExceptionThrownHandler);
+}
+
+
+int32_t DbgMessageQueue::LookupIsolateCommand(const char* buf,
+ int32_t buflen) {
+ // Check if we have a isolate specific debugger command.
+ int32_t i = 0;
+ while (debugger_commands[i].cmd_string != NULL) {
+ if (strncmp(buf, debugger_commands[i].cmd_string, buflen) == 0) {
+ return i;
+ }
+ i++;
+ }
+ return kInvalidCommand;
+}
+
+
+DbgMessageQueue* DbgMessageQueue::GetIsolateMessageQueue(Dart_Isolate isolate) {
+ // TODO(asiva): Return a message queue corresponding to the isolate.
+ // For now we use a static message queue object as we are only supporting
+ // debugging of a single isolate.
+ return message_queue;
+}
+
+
+void DbgMessageQueue::BptResolvedHandler(intptr_t bp_id,
+ Dart_Handle url,
+ intptr_t line_number) {
+ Dart_EnterScope();
+ dart::TextBuffer msg(128);
+ msg.Printf("{ \"event\": \"breakpointResolved\", \"params\": {");
+ msg.Printf("\"breakpointId\": %"Pd", \"url\":", bp_id);
+ FormatEncodedString(&msg, url);
+ msg.Printf(",\"line\": %"Pd" }}", line_number);
+ DbgMessageQueue* msg_queue = GetIsolateMessageQueue(Dart_CurrentIsolate());
+ ASSERT(msg_queue != NULL);
+ msg_queue->QueueOutputMsg(&msg);
+ Dart_ExitScope();
+}
+
+
+void DbgMessageQueue::BreakpointHandler(Dart_Breakpoint bpt,
+ Dart_StackTrace trace) {
+ DebuggerConnectionHandler::WaitForConnection();
+ Dart_EnterScope();
+ DbgMessageQueue* msg_queue = GetIsolateMessageQueue(Dart_CurrentIsolate());
+ ASSERT(msg_queue != NULL);
+ msg_queue->SendQueuedMsgs();
+ msg_queue->SendBreakpointEvent(trace);
+ msg_queue->HandleMessages();
+ Dart_ExitScope();
+}
+
+
+void DbgMessageQueue::ExceptionThrownHandler(Dart_Handle exception,
+ Dart_StackTrace stack_trace) {
+ DebuggerConnectionHandler::WaitForConnection();
+ Dart_EnterScope();
+ DbgMessageQueue* msg_queue = GetIsolateMessageQueue(Dart_CurrentIsolate());
+ ASSERT(msg_queue != NULL);
+ msg_queue->SendQueuedMsgs();
+ msg_queue->SendExceptionEvent(exception, stack_trace);
+ msg_queue->HandleMessages();
+ Dart_ExitScope();
+}
« runtime/bin/dbg_message.h ('K') | « runtime/bin/dbg_message.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698