| Index: runtime/bin/dbg_connection.cc
|
| ===================================================================
|
| --- runtime/bin/dbg_connection.cc (revision 7517)
|
| +++ runtime/bin/dbg_connection.cc (working copy)
|
| @@ -22,13 +22,21 @@
|
| MessageBuffer* DebuggerConnectionHandler::msgbuf_ = NULL;
|
|
|
| bool DebuggerConnectionHandler::handler_started_ = false;
|
| +bool DebuggerConnectionHandler::request_resume_ = false;
|
|
|
|
|
| // TODO(hausner): Need better error handling.
|
| #define ASSERT_NOT_ERROR(handle) \
|
| ASSERT(!Dart_IsError(handle))
|
|
|
| +typedef void (*CommandHandler)(const char* json_cmd);
|
|
|
| +struct JSONDebuggerCommand {
|
| + const char* cmd_string;
|
| + CommandHandler handler_function;
|
| +};
|
| +
|
| +
|
| class MessageBuffer {
|
| public:
|
| explicit MessageBuffer(int fd);
|
| @@ -37,6 +45,7 @@
|
| bool IsValidMessage() const;
|
| void PopMessage();
|
| int MessageId() const;
|
| + const char* Params() const;
|
| char* buf() const { return buf_; }
|
| bool Alive() const { return connection_is_alive_; }
|
|
|
| @@ -95,6 +104,17 @@
|
| }
|
|
|
|
|
| +const char* MessageBuffer::Params() const {
|
| + dart::JSONReader r(buf_);
|
| + r.Seek("param");
|
| + if (r.Type() == dart::JSONReader::kObject) {
|
| + return r.ValueChars();
|
| + } else {
|
| + return NULL;
|
| + }
|
| +}
|
| +
|
| +
|
| void MessageBuffer::ReadData() {
|
| ASSERT(data_length_ >= 0);
|
| ASSERT(data_length_ < buf_length_);
|
| @@ -145,17 +165,122 @@
|
| }
|
|
|
|
|
| -void DebuggerConnectionHandler::HandleResumeCmd() {
|
| +void DebuggerConnectionHandler::SendError(int msg_id,
|
| + const char* format, ...) {
|
| + dart::TextBuffer msg(64);
|
| + msg.Printf("{\"id\": %d, \"error\": \"", msg_id);
|
| + va_list args;
|
| + va_start(args, format);
|
| + msg.Printf(format, args);
|
| + va_end(args);
|
| + msg.Printf("\"}");
|
| + Socket::Write(debugger_fd_, msg.buf(), msg.length());
|
| + // TODO(hausner): Error checking. Probably just shut down the debugger
|
| + // session if we there is an error while writing.
|
| +}
|
| +
|
| +
|
| +void DebuggerConnectionHandler::HandleResumeCmd(const char* json_msg) {
|
| int msg_id = msgbuf_->MessageId();
|
| dart::TextBuffer msg(64);
|
| msg.Printf("{ \"id\": %d }", msg_id);
|
| Socket::Write(debugger_fd_, msg.buf(), msg.length());
|
| // TODO(hausner): Error checking. Probably just shut down the debugger
|
| // session if we there is an error while writing.
|
| + request_resume_ = true;
|
| }
|
|
|
|
|
| +void DebuggerConnectionHandler::HandleStepIntoCmd(const char* json_msg) {
|
| + Dart_Handle res = Dart_SetStepInto();
|
| + ASSERT_NOT_ERROR(res);
|
| + HandleResumeCmd(json_msg);
|
| +}
|
| +
|
| +
|
| +void DebuggerConnectionHandler::HandleStepOutCmd(const char* json_msg) {
|
| + Dart_Handle res = Dart_SetStepOut();
|
| + ASSERT_NOT_ERROR(res);
|
| + HandleResumeCmd(json_msg);
|
| +}
|
| +
|
| +
|
| +void DebuggerConnectionHandler::HandleStepOverCmd(const char* json_msg) {
|
| + Dart_Handle res = Dart_SetStepOver();
|
| + ASSERT_NOT_ERROR(res);
|
| + HandleResumeCmd(json_msg);
|
| +}
|
| +
|
| +
|
| +void DebuggerConnectionHandler::HandleGetScriptURLsCmd(const char* json_msg) {
|
| + int msg_id = msgbuf_->MessageId();
|
| + dart::TextBuffer msg(64);
|
| + const char* params = msgbuf_->Params();
|
| + ASSERT(params != NULL);
|
| + dart::JSONReader pr(params);
|
| + pr.Seek("library");
|
| + ASSERT(pr.Type() == dart::JSONReader::kString);
|
| + char lib_url_chars[128];
|
| + pr.GetValueChars(lib_url_chars, sizeof(lib_url_chars));
|
| + Dart_Handle lib_url = Dart_NewString(lib_url_chars);
|
| + ASSERT_NOT_ERROR(lib_url);
|
| + Dart_Handle urls = Dart_GetScriptURLs(lib_url);
|
| + if (Dart_IsError(urls)) {
|
| + SendError(msg_id, "Error: '%s'.", 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);
|
| + ASSERT(Dart_IsString(script_url));
|
| + char const* chars;
|
| + Dart_StringToCString(lib_url, &chars);
|
| + msg.Printf("%s\"%s\"", (i == 0) ? "" : ", ", chars);
|
| + }
|
| + msg.Printf("] }}");
|
| + Socket::Write(debugger_fd_, msg.buf(), msg.length());
|
| + // TODO(hausner): Error checking. Probably just shut down the debugger
|
| + // session if we there is an error while writing.
|
| +}
|
| +
|
| +
|
| +void DebuggerConnectionHandler::HandleGetLibraryURLsCmd(const char* json_msg) {
|
| + int msg_id = msgbuf_->MessageId();
|
| + dart::TextBuffer msg(64);
|
| + msg.Printf("{ \"id\": %d, \"result\": { \"urls\": [", msg_id);
|
| + Dart_Handle urls = Dart_GetLibraryURLs();
|
| + ASSERT_NOT_ERROR(urls);
|
| + intptr_t num_libs;
|
| + Dart_ListLength(urls, &num_libs);
|
| + for (int i = 0; i < num_libs; i++) {
|
| + Dart_Handle lib_url = Dart_ListGetAt(urls, i);
|
| + ASSERT(Dart_IsString(lib_url));
|
| + char const* chars;
|
| + Dart_StringToCString(lib_url, &chars);
|
| + msg.Printf("%s\"%s\"", (i == 0) ? "" : ", ", chars);
|
| + }
|
| + msg.Printf("] }}");
|
| + Socket::Write(debugger_fd_, msg.buf(), msg.length());
|
| + // TODO(hausner): Error checking. Probably just shut down the debugger
|
| + // session if we there is an error while writing.
|
| +}
|
| +
|
| +
|
| void DebuggerConnectionHandler::HandleMessages() {
|
| + static JSONDebuggerCommand debugger_commands[] = {
|
| + { "resume", HandleResumeCmd },
|
| + { "getLibraryURLs", HandleGetLibraryURLsCmd},
|
| + { "getScriptURLs", HandleGetScriptURLsCmd },
|
| + { "stepInto", HandleStepIntoCmd },
|
| + { "stepOut", HandleStepOutCmd },
|
| + { "stepOver", HandleStepOverCmd },
|
| + { NULL, NULL }
|
| + };
|
| +
|
| for (;;) {
|
| while (!msgbuf_->IsValidMessage() && msgbuf_->Alive()) {
|
| msgbuf_->ReadData();
|
| @@ -171,11 +296,23 @@
|
| if (!found) {
|
| printf("'command' not found in JSON message: '%s'\n", msgbuf_->buf());
|
| msgbuf_->PopMessage();
|
| - } else if (r.IsStringLiteral("resume")) {
|
| - HandleResumeCmd();
|
| - msgbuf_->PopMessage();
|
| - return;
|
| - } else {
|
| + }
|
| + int i = 0;
|
| + bool is_handled = false;
|
| + request_resume_ = false;
|
| + while (debugger_commands[i].cmd_string != NULL) {
|
| + if (r.IsStringLiteral(debugger_commands[i].cmd_string)) {
|
| + is_handled = true;
|
| + (*debugger_commands[i].handler_function)(msgbuf_->buf());
|
| + msgbuf_->PopMessage();
|
| + if (request_resume_) {
|
| + return;
|
| + }
|
| + break;
|
| + }
|
| + i++;
|
| + }
|
| + if (!is_handled) {
|
| printf("unrecognized command received: '%s'\n", msgbuf_->buf());
|
| msgbuf_->PopMessage();
|
| }
|
| @@ -189,7 +326,7 @@
|
| intptr_t trace_len = 0;
|
| Dart_Handle res = Dart_StackTraceLength(trace, &trace_len);
|
| ASSERT_NOT_ERROR(res);
|
| - msg.Printf("{ \"command\" : \"paused\", \"params\" : ");
|
| + msg.Printf("{ \"event\": \"paused\", \"params\": ");
|
| msg.Printf("{ \"callFrames\" : [ ");
|
| for (int i = 0; i < trace_len; i++) {
|
| Dart_ActivationFrame frame;
|
| @@ -204,7 +341,7 @@
|
| ASSERT(Dart_IsString(func_name));
|
| const char* func_name_chars;
|
| Dart_StringToCString(func_name, &func_name_chars);
|
| - msg.Printf("%s { \"functionName\" : \"%s\" , ",
|
| + msg.Printf("%s { \"functionName\": \"%s\" , ",
|
| i > 0 ? "," : "",
|
| func_name_chars);
|
| ASSERT(Dart_IsString(script_url));
|
| @@ -229,11 +366,13 @@
|
| ASSERT(res == dart::Monitor::kNotified);
|
| }
|
| }
|
| + Dart_EnterScope();
|
| SendBreakpointEvent(bpt, trace);
|
| HandleMessages();
|
| if (!msgbuf_->Alive()) {
|
| CloseDbgConnection();
|
| }
|
| + Dart_ExitScope();
|
| }
|
|
|
|
|
|
|