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

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

Issue 1497033003: - Remove the legacy debug protocol. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years 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
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "bin/dbg_connection.h"
6 #include "bin/dbg_message.h"
7 #include "bin/dartutils.h"
8 #include "bin/lockers.h"
9 #include "bin/thread.h"
10 #include "bin/utils.h"
11
12 #include "platform/globals.h"
13 #include "platform/json.h"
14 #include "platform/utils.h"
15
16 #include "include/dart_api.h"
17
18
19 namespace dart {
20 namespace bin {
21
22 bool MessageParser::IsValidMessage() const {
23 if (buf_length_ == 0) {
24 return false;
25 }
26 dart::JSONReader msg_reader(buf_);
27 return msg_reader.EndOfObject() != NULL;
28 }
29
30
31 int MessageParser::MessageId() const {
32 dart::JSONReader r(buf_);
33 r.Seek("id");
34 if (r.Type() == dart::JSONReader::kInteger) {
35 return atoi(r.ValueChars());
36 } else {
37 return -1;
38 }
39 }
40
41
42 const char* MessageParser::Params() const {
43 dart::JSONReader r(buf_);
44 r.Seek("params");
45 if (r.Type() == dart::JSONReader::kObject) {
46 return r.ValueChars();
47 } else {
48 return NULL;
49 }
50 }
51
52
53 bool MessageParser::HasParam(const char* name) const {
54 const char* params = Params();
55 ASSERT(params != NULL);
56 dart::JSONReader r(params);
57 return r.Seek(name);
58 }
59
60
61 intptr_t MessageParser::GetIntParam(const char* name) const {
62 const char* params = Params();
63 ASSERT(params != NULL);
64 dart::JSONReader r(params);
65 r.Seek(name);
66 ASSERT(r.Type() == dart::JSONReader::kInteger);
67 return strtol(r.ValueChars(), NULL, 10);
68 }
69
70
71 int64_t MessageParser::GetInt64Param(const char* name) const {
72 const char* params = Params();
73 ASSERT(params != NULL);
74 dart::JSONReader r(params);
75 r.Seek(name);
76 ASSERT(r.Type() == dart::JSONReader::kInteger);
77 return strtoll(r.ValueChars(), NULL, 10);
78 }
79
80
81 intptr_t MessageParser::GetOptIntParam(const char* name,
82 intptr_t default_val) const {
83 const char* params = Params();
84 ASSERT(params != NULL);
85 dart::JSONReader r(params);
86 r.Seek(name);
87 if (r.Type() == dart::JSONReader::kInteger) {
88 return strtol(r.ValueChars(), NULL, 10);
89 } else {
90 return default_val;
91 }
92 }
93
94
95 static const char* GetStringChars(Dart_Handle str) {
96 ASSERT(Dart_IsString(str));
97 const char* chars;
98 Dart_Handle res = Dart_StringToCString(str, &chars);
99 ASSERT(!Dart_IsError(res));
100 return chars;
101 }
102
103
104 static int64_t GetIntValue(Dart_Handle int_handle) {
105 int64_t int64_val = -1;
106 ASSERT(Dart_IsInteger(int_handle));
107 Dart_Handle res = Dart_IntegerToInt64(int_handle, &int64_val);
108 ASSERT_NOT_ERROR(res);
109 return int64_val;
110 }
111
112
113 char* MessageParser::GetStringParam(const char* name) const {
114 const char* params = Params();
115 ASSERT(params != NULL);
116 dart::JSONReader pr(params);
117 pr.Seek(name);
118 if (pr.Type() != dart::JSONReader::kString) {
119 return NULL;
120 }
121 intptr_t buflen = pr.ValueLen() + 1;
122 char* param_chars = reinterpret_cast<char*>(malloc(buflen));
123 pr.GetDecodedValueChars(param_chars, buflen);
124 return param_chars;
125 }
126
127
128 static void FormatEncodedCharsTrunc(dart::TextBuffer* buf,
129 Dart_Handle str,
130 intptr_t max_chars) {
131 intptr_t str_len = 0;
132 Dart_Handle res = Dart_StringLength(str, &str_len);
133 ASSERT_NOT_ERROR(res);
134 intptr_t num_chars = (str_len > max_chars) ? max_chars : str_len;
135 uint16_t* codeunits =
136 reinterpret_cast<uint16_t*>(malloc(num_chars * sizeof(uint16_t)));
137 ASSERT(codeunits != NULL);
138 intptr_t actual_len = num_chars;
139 res = Dart_StringToUTF16(str, codeunits, &actual_len);
140 ASSERT_NOT_ERROR(res);
141 ASSERT(num_chars == actual_len);
142 for (int i = 0; i < num_chars; i++) {
143 buf->EscapeAndAddCodeUnit(codeunits[i]);
144 }
145 if (str_len > max_chars) {
146 buf->Printf("...");
147 }
148 free(codeunits);
149 }
150
151
152 static void FormatEncodedChars(dart::TextBuffer* buf, Dart_Handle str) {
153 intptr_t str_len = 0;
154 Dart_Handle res = Dart_StringLength(str, &str_len);
155 ASSERT_NOT_ERROR(res);
156 uint16_t* codeunits =
157 reinterpret_cast<uint16_t*>(malloc(str_len * sizeof(uint16_t)));
158 ASSERT(codeunits != NULL);
159 intptr_t actual_len = str_len;
160 res = Dart_StringToUTF16(str, codeunits, &actual_len);
161 ASSERT_NOT_ERROR(res);
162 ASSERT(str_len == actual_len);
163 for (int i = 0; i < str_len; i++) {
164 buf->EscapeAndAddCodeUnit(codeunits[i]);
165 }
166 free(codeunits);
167 }
168
169
170 static void FormatEncodedString(dart::TextBuffer* buf, Dart_Handle str) {
171 buf->AddChar('\"');
172 FormatEncodedChars(buf, str);
173 buf->AddChar('\"');
174 }
175
176
177 static void FormatTextualValue(dart::TextBuffer* buf,
178 Dart_Handle object,
179 intptr_t max_chars,
180 bool expand_list);
181
182
183 static void FormatTextualListValue(dart::TextBuffer* buf,
184 Dart_Handle list,
185 intptr_t max_chars) {
186 intptr_t len = 0;
187 Dart_Handle res = Dart_ListLength(list, &len);
188 ASSERT_NOT_ERROR(res);
189 const intptr_t initial_buffer_length = buf->length();
190 // Maximum number of characters we print for array elements.
191 const intptr_t max_buffer_length = initial_buffer_length + max_chars;
192 buf->Printf("[");
193 for (int i = 0; i < len; i++) {
194 if (i > 0) {
195 buf->Printf(", ");
196 }
197 Dart_Handle elem = Dart_ListGetAt(list, i);
198 const intptr_t max_element_chars = 50;
199 FormatTextualValue(buf, elem, max_element_chars, false);
200 if (buf->length() > max_buffer_length) {
201 buf->Printf(", ...");
202 break;
203 }
204 }
205 buf->Printf("]");
206 }
207
208
209 static void FormatTextualValue(dart::TextBuffer* buf,
210 Dart_Handle object,
211 intptr_t max_chars,
212 bool expand_list) {
213 ASSERT(!Dart_IsError(object));
214 if (Dart_IsList(object)) {
215 if (expand_list) {
216 FormatTextualListValue(buf, object, max_chars);
217 } else {
218 buf->Printf("[...]");
219 }
220 } else if (Dart_IsNull(object)) {
221 buf->Printf("null");
222 } else if (Dart_IsString(object)) {
223 buf->Printf("\\\"");
224 FormatEncodedCharsTrunc(buf, object, max_chars);
225 buf->Printf("\\\"");
226 } else if (Dart_IsNumber(object) || Dart_IsBoolean(object)) {
227 Dart_Handle text = Dart_ToString(object);
228 ASSERT(!Dart_IsNull(text) && !Dart_IsError(text));
229 FormatEncodedCharsTrunc(buf, text, max_chars);
230 } else {
231 Dart_Handle type = Dart_InstanceGetType(object);
232 ASSERT_NOT_ERROR(type);
233 type = Dart_ToString(type);
234 ASSERT_NOT_ERROR(type);
235 buf->Printf("object of type ");
236 FormatEncodedCharsTrunc(buf, type, max_chars);
237 }
238 }
239
240
241 static void FormatValue(dart::TextBuffer* buf, Dart_Handle object) {
242 bool print_text_field = true;
243 if (Dart_IsNumber(object)) {
244 buf->Printf("\"kind\":\"number\"");
245 } else if (Dart_IsString(object)) {
246 buf->Printf("\"kind\":\"string\"");
247 } else if (Dart_IsBoolean(object)) {
248 buf->Printf("\"kind\":\"boolean\"");
249 } else if (Dart_IsList(object)) {
250 intptr_t len = 0;
251 Dart_Handle res = Dart_ListLength(object, &len);
252 ASSERT_NOT_ERROR(res);
253 buf->Printf("\"kind\":\"list\",\"length\":%" Pd "", len);
254 } else if (Dart_IsClosure(object)) {
255 Dart_Handle name, signature;
256 Dart_CodeLocation location;
257 Dart_Handle res = Dart_GetClosureInfo(object, &name, &signature, &location);
258 ASSERT_NOT_ERROR(res);
259 buf->Printf("\"kind\":\"function\",\"name\":\"%s\"", GetStringChars(name));
260 buf->Printf(",\"signature\":\"%s\"", GetStringChars(signature));
261 if (!Dart_IsNull(location.script_url)) {
262 ASSERT(Dart_IsString(location.script_url));
263 buf->Printf(",\"location\": { \"url\":");
264 FormatEncodedString(buf, location.script_url);
265 buf->Printf(",\"libraryId\":%d,", location.library_id);
266 buf->Printf("\"tokenOffset\":%d}", location.token_pos);
267 }
268 print_text_field = false;
269 } else {
270 buf->Printf("\"kind\":\"object\"");
271 intptr_t class_id = 0;
272 Dart_Handle res = Dart_GetObjClassId(object, &class_id);
273 if (!Dart_IsError(res)) {
274 buf->Printf(",\"classId\":%" Pd "", class_id);
275 }
276 }
277 if (print_text_field) {
278 buf->Printf(",\"text\":\"");
279 const intptr_t max_chars = 1024;
280 FormatTextualValue(buf, object, max_chars, true);
281 buf->Printf("\"");
282 }
283 }
284
285
286 static void FormatValueObj(dart::TextBuffer* buf, Dart_Handle object) {
287 buf->Printf("{");
288 FormatValue(buf, object);
289 buf->Printf("}");
290 }
291
292
293 static void FormatRemoteObj(dart::TextBuffer* buf, Dart_Handle object) {
294 intptr_t obj_id = Dart_CacheObject(object);
295 ASSERT(obj_id >= 0);
296 buf->Printf("{\"objectId\":%" Pd ",", obj_id);
297 FormatValue(buf, object);
298 buf->Printf("}");
299 }
300
301
302 static void FormatNamedValue(dart::TextBuffer* buf,
303 Dart_Handle object_name,
304 Dart_Handle object) {
305 ASSERT(Dart_IsString(object_name));
306 buf->Printf("{\"name\":\"%s\",", GetStringChars(object_name));
307 buf->Printf("\"value\":");
308 FormatRemoteObj(buf, object);
309 buf->Printf("}");
310 }
311
312
313 static void FormatNamedValueList(dart::TextBuffer* buf,
314 Dart_Handle obj_list) {
315 ASSERT(Dart_IsList(obj_list));
316 intptr_t list_length = 0;
317 Dart_Handle res = Dart_ListLength(obj_list, &list_length);
318 ASSERT_NOT_ERROR(res);
319 ASSERT(list_length % 2 == 0);
320 buf->Printf("[");
321 for (int i = 0; i + 1 < list_length; i += 2) {
322 Dart_Handle name_handle = Dart_ListGetAt(obj_list, i);
323 ASSERT_NOT_ERROR(name_handle);
324 Dart_Handle value_handle = Dart_ListGetAt(obj_list, i + 1);
325 ASSERT_NOT_ERROR(value_handle);
326 if (i > 0) {
327 buf->Printf(",");
328 }
329 FormatNamedValue(buf, name_handle, value_handle);
330 }
331 buf->Printf("]");
332 }
333
334
335 static const char* FormatClassProps(dart::TextBuffer* buf,
336 intptr_t cls_id) {
337 Dart_Handle name, static_fields;
338 intptr_t super_id = -1;
339 intptr_t library_id = -1;
340 Dart_Handle res =
341 Dart_GetClassInfo(cls_id, &name, &library_id, &super_id, &static_fields);
342 RETURN_IF_ERROR(res);
343 RETURN_IF_ERROR(name);
344 buf->Printf("{\"name\":\"%s\",", GetStringChars(name));
345 if (super_id > 0) {
346 buf->Printf("\"superclassId\":%" Pd ",", super_id);
347 }
348 buf->Printf("\"libraryId\":%" Pd ",", library_id);
349 RETURN_IF_ERROR(static_fields);
350 buf->Printf("\"fields\":");
351 FormatNamedValueList(buf, static_fields);
352 buf->Printf("}");
353 return NULL;
354 }
355
356
357 static const char* FormatLibraryProps(dart::TextBuffer* buf,
358 intptr_t lib_id) {
359 Dart_Handle url = Dart_GetLibraryURL(lib_id);
360 RETURN_IF_ERROR(url);
361 buf->Printf("{\"url\":");
362 FormatEncodedString(buf, url);
363
364 // Whether debugging is enabled.
365 bool is_debuggable = false;
366 Dart_Handle res = Dart_GetLibraryDebuggable(lib_id, &is_debuggable);
367 RETURN_IF_ERROR(res);
368 buf->Printf(",\"debuggingEnabled\":%s",
369 is_debuggable ? "\"true\"" : "\"false\"");
370
371 // Imports and prefixes.
372 Dart_Handle import_list = Dart_GetLibraryImports(lib_id);
373 RETURN_IF_ERROR(import_list);
374 ASSERT(Dart_IsList(import_list));
375 intptr_t list_length = 0;
376 res = Dart_ListLength(import_list, &list_length);
377 RETURN_IF_ERROR(res);
378 buf->Printf(",\"imports\":[");
379 for (intptr_t i = 0; i + 1 < list_length; i += 2) {
380 Dart_Handle lib_id = Dart_ListGetAt(import_list, i + 1);
381 ASSERT_NOT_ERROR(lib_id);
382 buf->Printf("%s{\"libraryId\":%" Pd64 ",",
383 (i > 0) ? ",": "",
384 GetIntValue(lib_id));
385
386 Dart_Handle name = Dart_ListGetAt(import_list, i);
387 ASSERT_NOT_ERROR(name);
388 buf->Printf("\"prefix\":\"%s\"}",
389 Dart_IsNull(name) ? "" : GetStringChars(name));
390 }
391 buf->Printf("],");
392
393 // Global variables in the library.
394 Dart_Handle global_vars = Dart_GetLibraryFields(lib_id);
395 RETURN_IF_ERROR(global_vars);
396 buf->Printf("\"globals\":");
397 FormatNamedValueList(buf, global_vars);
398 buf->Printf("}");
399 return NULL;
400 }
401
402
403 static const char* FormatObjProps(dart::TextBuffer* buf,
404 Dart_Handle object) {
405 intptr_t class_id;
406 if (Dart_IsNull(object)) {
407 buf->Printf("{\"classId\":-1,\"fields\":[]}");
408 return NULL;
409 }
410 Dart_Handle res = Dart_GetObjClassId(object, &class_id);
411 RETURN_IF_ERROR(res);
412 buf->Printf("{\"classId\": %" Pd ",", class_id);
413 buf->Printf("\"kind\":\"object\",\"fields\":");
414 Dart_Handle fields = Dart_GetInstanceFields(object);
415 RETURN_IF_ERROR(fields);
416 FormatNamedValueList(buf, fields);
417 buf->Printf("}");
418 return NULL;
419 }
420
421
422 static const char* FormatListSlice(dart::TextBuffer* buf,
423 Dart_Handle list,
424 intptr_t list_length,
425 intptr_t index,
426 intptr_t slice_length) {
427 intptr_t end_index = index + slice_length;
428 ASSERT(end_index <= list_length);
429 buf->Printf("{\"index\":%" Pd ",", index);
430 buf->Printf("\"length\":%" Pd ",", slice_length);
431 buf->Printf("\"elements\":[");
432 for (intptr_t i = index; i < end_index; i++) {
433 Dart_Handle value = Dart_ListGetAt(list, i);
434 if (i > index) {
435 buf->Printf(",");
436 }
437 FormatValueObj(buf, value);
438 }
439 buf->Printf("]}");
440 return NULL;
441 }
442
443
444 static void FormatLocationFromTrace(dart::TextBuffer* msg,
445 Dart_StackTrace trace,
446 const char* prefix) {
447 intptr_t trace_len = 0;
448 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len);
449 ASSERT_NOT_ERROR(res);
450 if (trace_len == 0) {
451 return;
452 }
453 Dart_ActivationFrame frame;
454 res = Dart_GetActivationFrame(trace, 0, &frame);
455 ASSERT_NOT_ERROR(res);
456 Dart_CodeLocation location;
457 res = Dart_ActivationFrameGetLocation(frame, NULL, NULL, &location);
458 ASSERT_NOT_ERROR(res);
459 if (!Dart_IsNull(location.script_url)) {
460 ASSERT(Dart_IsString(location.script_url));
461 msg->Printf("%s\"location\": { \"url\":", prefix);
462 FormatEncodedString(msg, location.script_url);
463 msg->Printf(",\"libraryId\":%d,", location.library_id);
464 msg->Printf("\"tokenOffset\":%d}", location.token_pos);
465 }
466 }
467
468
469 static void FormatCallFrames(dart::TextBuffer* msg, Dart_StackTrace trace) {
470 intptr_t trace_len = 0;
471 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len);
472 ASSERT_NOT_ERROR(res);
473 msg->Printf("\"callFrames\" : [ ");
474 for (int i = 0; i < trace_len; i++) {
475 Dart_ActivationFrame frame;
476 res = Dart_GetActivationFrame(trace, i, &frame);
477 ASSERT_NOT_ERROR(res);
478 Dart_Handle func_name;
479 Dart_Handle func;
480 Dart_CodeLocation location;
481 res = Dart_ActivationFrameGetLocation(frame, &func_name, &func, &location);
482 ASSERT_NOT_ERROR(res);
483 ASSERT(Dart_IsString(func_name));
484 msg->Printf("%s{\"functionName\":", (i > 0) ? "," : "");
485 FormatEncodedString(msg, func_name);
486 if (!Dart_IsNull(location.script_url)) {
487 ASSERT(Dart_IsString(location.script_url));
488 msg->Printf(",\"location\": { \"url\":");
489 FormatEncodedString(msg, location.script_url);
490 msg->Printf(",\"libraryId\":%d,", location.library_id);
491 msg->Printf("\"tokenOffset\":%d}", location.token_pos);
492 }
493 ASSERT_NOT_ERROR(func);
494 Dart_Handle origin = Dart_GetFunctionOrigin(func);
495 ASSERT_NOT_ERROR(origin);
496 if (Dart_IsInteger(origin)) {
497 int64_t class_id = GetIntValue(origin);
498 msg->Printf(",\"classId\":%" Pd64 "", class_id);
499 }
500 Dart_Handle locals = Dart_GetLocalVariables(frame);
501 ASSERT_NOT_ERROR(locals);
502 msg->Printf(",\"locals\":");
503 FormatNamedValueList(msg, locals);
504 msg->Printf("}");
505 }
506 msg->Printf("]");
507 }
508
509
510 typedef bool (*CommandHandler)(DbgMessage* msg);
511
512 struct JSONDebuggerCommand {
513 const char* cmd_string;
514 CommandHandler handler_function;
515 };
516
517
518 static JSONDebuggerCommand debugger_commands[] = {
519 { "resume", DbgMessage::HandleResumeCmd },
520 { "stepInto", DbgMessage::HandleStepIntoCmd },
521 { "stepOut", DbgMessage::HandleStepOutCmd },
522 { "stepOver", DbgMessage::HandleStepOverCmd },
523 { "getLibraries", DbgMessage::HandleGetLibrariesCmd },
524 { "getClassProperties", DbgMessage::HandleGetClassPropsCmd },
525 { "getLibraryProperties", DbgMessage::HandleGetLibPropsCmd },
526 { "setLibraryProperties", DbgMessage::HandleSetLibPropsCmd },
527 { "evaluateExpr", DbgMessage::HandleEvaluateExprCmd },
528 { "getObjectProperties", DbgMessage::HandleGetObjPropsCmd },
529 { "getListElements", DbgMessage::HandleGetListCmd },
530 { "getGlobalVariables", DbgMessage::HandleGetGlobalsCmd },
531 { "getScriptURLs", DbgMessage::HandleGetScriptURLsCmd },
532 { "getScriptSource", DbgMessage::HandleGetSourceCmd },
533 { "getLineNumberTable", DbgMessage::HandleGetLineNumbersCmd },
534 { "getStackTrace", DbgMessage::HandleGetStackTraceCmd },
535 { "setBreakpoint", DbgMessage::HandleSetBpCmd },
536 { "setPauseOnException", DbgMessage::HandlePauseOnExcCmd },
537 { "removeBreakpoint", DbgMessage::HandleRemBpCmd },
538 { NULL, NULL }
539 };
540
541
542 bool DbgMessage::HandleMessage() {
543 // Dispatch to the appropriate handler for the command.
544 int max_index = (sizeof(debugger_commands) / sizeof(JSONDebuggerCommand));
545 ASSERT(cmd_idx_ < max_index);
546 return (*debugger_commands[cmd_idx_].handler_function)(this);
547 }
548
549
550 void DbgMessage::SendReply(dart::TextBuffer* reply) {
551 DebuggerConnectionHandler::SendMsg(debug_fd(), reply);
552 }
553
554
555 void DbgMessage::SendErrorReply(int msg_id, const char* err_msg) {
556 DebuggerConnectionHandler::SendError(debug_fd(), msg_id, err_msg);
557 }
558
559
560 bool DbgMessage::HandleResumeCmd(DbgMessage* in_msg) {
561 ASSERT(in_msg != NULL);
562 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
563 int msg_id = msg_parser.MessageId();
564 dart::TextBuffer msg(64);
565 msg.Printf("{ \"id\": %d }", msg_id);
566 in_msg->SendReply(&msg);
567 return true;
568 }
569
570
571 bool DbgMessage::HandleStepIntoCmd(DbgMessage* in_msg) {
572 Dart_Handle res = Dart_SetStepInto();
573 ASSERT_NOT_ERROR(res);
574 return HandleResumeCmd(in_msg);
575 }
576
577
578 bool DbgMessage::HandleStepOutCmd(DbgMessage* in_msg) {
579 Dart_Handle res = Dart_SetStepOut();
580 ASSERT_NOT_ERROR(res);
581 return HandleResumeCmd(in_msg);
582 }
583
584
585 bool DbgMessage::HandleStepOverCmd(DbgMessage* in_msg) {
586 Dart_Handle res = Dart_SetStepOver();
587 ASSERT_NOT_ERROR(res);
588 return HandleResumeCmd(in_msg);
589 }
590
591
592 bool DbgMessage::HandleGetLibrariesCmd(DbgMessage* in_msg) {
593 ASSERT(in_msg != NULL);
594 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
595 int msg_id = msg_parser.MessageId();
596 dart::TextBuffer msg(64);
597 msg.Printf("{ \"id\": %d, \"result\": { \"libraries\": [", msg_id);
598 Dart_Handle lib_ids = Dart_GetLibraryIds();
599 ASSERT_NOT_ERROR(lib_ids);
600 intptr_t num_libs;
601 Dart_Handle res = Dart_ListLength(lib_ids, &num_libs);
602 ASSERT_NOT_ERROR(res);
603 for (intptr_t i = 0; i < num_libs; i++) {
604 Dart_Handle lib_id_handle = Dart_ListGetAt(lib_ids, i);
605 ASSERT(Dart_IsInteger(lib_id_handle));
606 int64_t lib_id = GetIntValue(lib_id_handle);
607 ASSERT((lib_id >= kIntptrMin) && (lib_id <= kIntptrMax));
608 Dart_Handle lib_url = Dart_GetLibraryURL(static_cast<intptr_t>(lib_id));
609 ASSERT_NOT_ERROR(lib_url);
610 ASSERT(Dart_IsString(lib_url));
611 msg.Printf("%s{\"id\":%" Pd64 ",\"url\":", (i == 0) ? "" : ", ", lib_id);
612 FormatEncodedString(&msg, lib_url);
613 msg.Printf("}");
614 }
615 msg.Printf("]}}");
616 in_msg->SendReply(&msg);
617 return false;
618 }
619
620
621 bool DbgMessage::HandleGetClassPropsCmd(DbgMessage* in_msg) {
622 ASSERT(in_msg != NULL);
623 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
624 int msg_id = msg_parser.MessageId();
625 intptr_t cls_id = msg_parser.GetIntParam("classId");
626 dart::TextBuffer msg(64);
627 msg.Printf("{\"id\":%d, \"result\":", msg_id);
628 const char* err = FormatClassProps(&msg, cls_id);
629 if (err != NULL) {
630 in_msg->SendErrorReply(msg_id, err);
631 return false;
632 }
633 msg.Printf("}");
634 in_msg->SendReply(&msg);
635 return false;
636 }
637
638
639 bool DbgMessage::HandleGetLibPropsCmd(DbgMessage* in_msg) {
640 ASSERT(in_msg != NULL);
641 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
642 int msg_id = msg_parser.MessageId();
643 intptr_t lib_id = msg_parser.GetIntParam("libraryId");
644 dart::TextBuffer msg(64);
645 msg.Printf("{\"id\":%d, \"result\":", msg_id);
646 const char* err = FormatLibraryProps(&msg, lib_id);
647 if (err != NULL) {
648 in_msg->SendErrorReply(msg_id, err);
649 return false;
650 }
651 msg.Printf("}");
652 in_msg->SendReply(&msg);
653 return false;
654 }
655
656
657 bool DbgMessage::HandleSetLibPropsCmd(DbgMessage* in_msg) {
658 ASSERT(in_msg != NULL);
659 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
660 int msg_id = msg_parser.MessageId();
661 intptr_t lib_id = msg_parser.GetIntParam("libraryId");
662 const char* enable_request = msg_parser.GetStringParam("debuggingEnabled");
663 bool enable;
664 if (strcmp(enable_request, "true") == 0) {
665 enable = true;
666 } else if (strcmp(enable_request, "false") == 0) {
667 enable = false;
668 } else {
669 in_msg->SendErrorReply(msg_id, "illegal argument for 'debuggingEnabled'");
670 return false;
671 }
672 Dart_Handle res = Dart_SetLibraryDebuggable(lib_id, enable);
673 if (Dart_IsError(res)) {
674 in_msg->SendErrorReply(msg_id, Dart_GetError(res));
675 return false;
676 }
677 bool enabled = false;
678 res = Dart_GetLibraryDebuggable(lib_id, &enabled);
679 if (Dart_IsError(res)) {
680 in_msg->SendErrorReply(msg_id, Dart_GetError(res));
681 return false;
682 }
683 dart::TextBuffer msg(64);
684 msg.Printf("{\"id\":%d, \"result\": {\"debuggingEnabled\": \"%s\"}}",
685 msg_id,
686 enabled ? "true" : "false");
687 in_msg->SendReply(&msg);
688 return false;
689 }
690
691
692 bool DbgMessage::HandleEvaluateExprCmd(DbgMessage* in_msg) {
693 ASSERT(in_msg != NULL);
694 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
695 int msg_id = msg_parser.MessageId();
696 Dart_Handle target = Dart_Null();
697 Dart_ActivationFrame frame = NULL;
698
699 if (msg_parser.HasParam("libraryId")) {
700 intptr_t lib_id = msg_parser.GetIntParam("libraryId");
701 target = Dart_GetLibraryFromId(lib_id);
702 } else if (msg_parser.HasParam("classId")) {
703 intptr_t cls_id = msg_parser.GetIntParam("classId");
704 target = Dart_GetClassFromId(cls_id);
705 } else if (msg_parser.HasParam("objectId")) {
706 intptr_t obj_id = msg_parser.GetIntParam("objectId");
707 target = Dart_GetCachedObject(obj_id);
708 } else if (msg_parser.HasParam("frameId")) {
709 intptr_t frame_index = msg_parser.GetIntParam("frameId");
710 Dart_Handle res;
711 Dart_StackTrace stack_trace;
712 res = Dart_GetStackTrace(&stack_trace);
713 ASSERT_NOT_ERROR(res);
714 intptr_t trace_length = 0;
715 res = Dart_StackTraceLength(stack_trace, &trace_length);
716 ASSERT_NOT_ERROR(res);
717 if (frame_index >= trace_length) {
718 in_msg->SendErrorReply(msg_id, "illegal frame index");
719 return false;
720 }
721 res = Dart_GetActivationFrame(stack_trace, frame_index, &frame);
722 ASSERT_NOT_ERROR(res);
723 } else {
724 in_msg->SendErrorReply(msg_id, "illegal evaluation target");
725 return false;
726 }
727
728 char* expr_chars = msg_parser.GetStringParam("expression");
729 Dart_Handle expr = Dart_NewStringFromCString(expr_chars);
730 if (Dart_IsError(expr)) {
731 in_msg->SendErrorReply(msg_id, Dart_GetError(expr));
732 return false;
733 }
734
735 Dart_Handle eval_result = Dart_Null();
736 if (frame != NULL) {
737 eval_result = Dart_ActivationFrameEvaluate(frame, expr);
738 } else {
739 if (Dart_IsError(target)) {
740 in_msg->SendErrorReply(msg_id, Dart_GetError(target));
741 return false;
742 }
743 eval_result = Dart_EvaluateExpr(target, expr);
744 }
745 if (Dart_IsError(eval_result)) {
746 in_msg->SendErrorReply(msg_id, Dart_GetError(eval_result));
747 return false;
748 }
749
750 dart::TextBuffer msg(64);
751 msg.Printf("{\"id\":%d, \"result\":", msg_id);
752 FormatRemoteObj(&msg, eval_result);
753 msg.Printf("}");
754 in_msg->SendReply(&msg);
755 return false;
756 }
757
758
759 bool DbgMessage::HandleGetObjPropsCmd(DbgMessage* in_msg) {
760 ASSERT(in_msg != NULL);
761 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
762 int msg_id = msg_parser.MessageId();
763 intptr_t obj_id = msg_parser.GetIntParam("objectId");
764 Dart_Handle obj = Dart_GetCachedObject(obj_id);
765 if (Dart_IsError(obj)) {
766 in_msg->SendErrorReply(msg_id, Dart_GetError(obj));
767 return false;
768 }
769 dart::TextBuffer msg(64);
770 msg.Printf("{\"id\":%d, \"result\":", msg_id);
771 const char* err = FormatObjProps(&msg, obj);
772 if (err != NULL) {
773 in_msg->SendErrorReply(msg_id, err);
774 return false;
775 }
776 msg.Printf("}");
777 in_msg->SendReply(&msg);
778 return false;
779 }
780
781
782 bool DbgMessage::HandleGetListCmd(DbgMessage* in_msg) {
783 const intptr_t kDefaultSliceLength = 100;
784 ASSERT(in_msg != NULL);
785 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
786 int msg_id = msg_parser.MessageId();
787 intptr_t obj_id = msg_parser.GetIntParam("objectId");
788 Dart_Handle list = Dart_GetCachedObject(obj_id);
789 if (Dart_IsError(list)) {
790 in_msg->SendErrorReply(msg_id, Dart_GetError(list));
791 return false;
792 }
793 if (!Dart_IsList(list)) {
794 in_msg->SendErrorReply(msg_id, "object is not a list");
795 return false;
796 }
797 intptr_t list_length = 0;
798 Dart_Handle res = Dart_ListLength(list, &list_length);
799 if (Dart_IsError(res)) {
800 in_msg->SendErrorReply(msg_id, Dart_GetError(res));
801 return false;
802 }
803
804 intptr_t index = msg_parser.GetIntParam("index");
805 if (index < 0) {
806 index = 0;
807 } else if (index > list_length) {
808 index = list_length;
809 }
810
811 // If no slice length is given, get only one element. If slice length
812 // is given as 0, get entire list.
813 intptr_t slice_length = msg_parser.GetOptIntParam("length", 1);
814 if (slice_length == 0) {
815 slice_length = list_length - index;
816 }
817 if ((index + slice_length) > list_length) {
818 slice_length = list_length - index;
819 }
820 ASSERT(slice_length >= 0);
821 if (slice_length > kDefaultSliceLength) {
822 slice_length = kDefaultSliceLength;
823 }
824 dart::TextBuffer msg(64);
825 msg.Printf("{\"id\":%d, \"result\":", msg_id);
826 if (slice_length == 1) {
827 Dart_Handle value = Dart_ListGetAt(list, index);
828 FormatRemoteObj(&msg, value);
829 } else {
830 FormatListSlice(&msg, list, list_length, index, slice_length);
831 }
832 msg.Printf("}");
833 in_msg->SendReply(&msg);
834 return false;
835 }
836
837
838 bool DbgMessage::HandleGetGlobalsCmd(DbgMessage* in_msg) {
839 ASSERT(in_msg != NULL);
840 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
841 int msg_id = msg_parser.MessageId();
842 intptr_t lib_id = msg_parser.GetIntParam("libraryId");
843 dart::TextBuffer msg(64);
844 msg.Printf("{\"id\":%d, \"result\": { \"globals\":", msg_id);
845 Dart_Handle globals = Dart_GetGlobalVariables(lib_id);
846 ASSERT_NOT_ERROR(globals);
847 FormatNamedValueList(&msg, globals);
848 msg.Printf("}}");
849 in_msg->SendReply(&msg);
850 return false;
851 }
852
853
854 bool DbgMessage::HandleGetScriptURLsCmd(DbgMessage* in_msg) {
855 ASSERT(in_msg != NULL);
856 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
857 int msg_id = msg_parser.MessageId();
858 dart::TextBuffer msg(64);
859 intptr_t lib_id = msg_parser.GetIntParam("libraryId");
860 Dart_Handle lib_url = Dart_GetLibraryURL(lib_id);
861 ASSERT_NOT_ERROR(lib_url);
862 Dart_Handle urls = Dart_GetScriptURLs(lib_url);
863 if (Dart_IsError(urls)) {
864 in_msg->SendErrorReply(msg_id, Dart_GetError(urls));
865 return false;
866 }
867 ASSERT(Dart_IsList(urls));
868 intptr_t num_urls = 0;
869 Dart_ListLength(urls, &num_urls);
870 msg.Printf("{ \"id\": %d, ", msg_id);
871 msg.Printf("\"result\": { \"urls\": [");
872 for (int i = 0; i < num_urls; i++) {
873 Dart_Handle script_url = Dart_ListGetAt(urls, i);
874 if (i > 0) {
875 msg.Printf(",");
876 }
877 FormatEncodedString(&msg, script_url);
878 }
879 msg.Printf("]}}");
880 in_msg->SendReply(&msg);
881 return false;
882 }
883
884
885 bool DbgMessage::HandleGetSourceCmd(DbgMessage* in_msg) {
886 ASSERT(in_msg != NULL);
887 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
888 int msg_id = msg_parser.MessageId();
889 dart::TextBuffer msg(64);
890 intptr_t lib_id = msg_parser.GetIntParam("libraryId");
891 char* url_chars = msg_parser.GetStringParam("url");
892 ASSERT(url_chars != NULL);
893 Dart_Handle url = DartUtils::NewString(url_chars);
894 ASSERT_NOT_ERROR(url);
895 free(url_chars);
896 url_chars = NULL;
897 Dart_Handle source = Dart_ScriptGetSource(lib_id, url);
898 if (Dart_IsError(source)) {
899 in_msg->SendErrorReply(msg_id, Dart_GetError(source));
900 return false;
901 }
902 msg.Printf("{ \"id\": %d, ", msg_id);
903 msg.Printf("\"result\": { \"text\": ");
904 FormatEncodedString(&msg, source);
905 msg.Printf("}}");
906 in_msg->SendReply(&msg);
907 return false;
908 }
909
910
911 bool DbgMessage::HandleGetLineNumbersCmd(DbgMessage* in_msg) {
912 ASSERT(in_msg != NULL);
913 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
914 int msg_id = msg_parser.MessageId();
915 dart::TextBuffer msg(64);
916 intptr_t lib_id = msg_parser.GetIntParam("libraryId");
917 char* url_chars = msg_parser.GetStringParam("url");
918 ASSERT(url_chars != NULL);
919 Dart_Handle url = DartUtils::NewString(url_chars);
920 ASSERT_NOT_ERROR(url);
921 free(url_chars);
922 url_chars = NULL;
923 Dart_Handle info = Dart_ScriptGetTokenInfo(lib_id, url);
924 if (Dart_IsError(info)) {
925 in_msg->SendErrorReply(msg_id, Dart_GetError(info));
926 return false;
927 }
928 ASSERT(Dart_IsList(info));
929 intptr_t info_len = 0;
930 Dart_Handle res = Dart_ListLength(info, &info_len);
931 ASSERT_NOT_ERROR(res);
932 msg.Printf("{ \"id\": %d, ", msg_id);
933 msg.Printf("\"result\": { \"lines\": [");
934 Dart_Handle elem;
935 intptr_t num_elems = 0;
936 for (intptr_t i = 0; i < info_len; i++) {
937 elem = Dart_ListGetAt(info, i);
938 if (Dart_IsNull(elem)) {
939 msg.Printf((i == 0) ? "[" : "], [");
940 num_elems = 0;
941 } else {
942 ASSERT(Dart_IsInteger(elem));
943 int64_t value = GetIntValue(elem);
944 if (num_elems == 0) {
945 msg.Printf("%" Pd64 "", value);
946 } else {
947 msg.Printf(",%" Pd64 "", value);
948 }
949 num_elems++;
950 }
951 }
952 msg.Printf("]]}}");
953 in_msg->SendReply(&msg);
954 return false;
955 }
956
957
958 bool DbgMessage::HandleGetStackTraceCmd(DbgMessage* in_msg) {
959 ASSERT(in_msg != NULL);
960 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
961 int msg_id = msg_parser.MessageId();
962 Dart_StackTrace trace;
963 Dart_Handle res = Dart_GetStackTrace(&trace);
964 ASSERT_NOT_ERROR(res);
965 dart::TextBuffer msg(128);
966 msg.Printf("{ \"id\": %d, \"result\": {", msg_id);
967 FormatCallFrames(&msg, trace);
968 msg.Printf("}}");
969 in_msg->SendReply(&msg);
970 return false;
971 }
972
973
974 bool DbgMessage::HandleSetBpCmd(DbgMessage* in_msg) {
975 ASSERT(in_msg != NULL);
976 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
977 int msg_id = msg_parser.MessageId();
978 char* url_chars = msg_parser.GetStringParam("url");
979 ASSERT(url_chars != NULL);
980 Dart_Handle url = DartUtils::NewString(url_chars);
981 ASSERT_NOT_ERROR(url);
982 free(url_chars);
983 url_chars = NULL;
984 intptr_t line_number = msg_parser.GetIntParam("line");
985 Dart_Handle bp_id = Dart_SetBreakpoint(url, line_number);
986 if (Dart_IsError(bp_id)) {
987 in_msg->SendErrorReply(msg_id, Dart_GetError(bp_id));
988 return false;
989 }
990 ASSERT(Dart_IsInteger(bp_id));
991 uint64_t bp_id_value;
992 Dart_Handle res = Dart_IntegerToUint64(bp_id, &bp_id_value);
993 ASSERT_NOT_ERROR(res);
994 dart::TextBuffer msg(64);
995 msg.Printf("{ \"id\": %d, \"result\": { \"breakpointId\": %" Pu64 " }}",
996 msg_id, bp_id_value);
997 in_msg->SendReply(&msg);
998 return false;
999 }
1000
1001
1002 bool DbgMessage::HandlePauseOnExcCmd(DbgMessage* in_msg) {
1003 ASSERT(in_msg != NULL);
1004 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
1005 int msg_id = msg_parser.MessageId();
1006 char* exc_chars = msg_parser.GetStringParam("exceptions");
1007 Dart_ExceptionPauseInfo info = kNoPauseOnExceptions;
1008 if (strcmp(exc_chars, "none") == 0) {
1009 info = kNoPauseOnExceptions;
1010 } else if (strcmp(exc_chars, "all") == 0) {
1011 info = kPauseOnAllExceptions;
1012 } else if (strcmp(exc_chars, "unhandled") == 0) {
1013 info = kPauseOnUnhandledExceptions;
1014 } else {
1015 in_msg->SendErrorReply(msg_id, "illegal value for parameter 'exceptions'");
1016 return false;
1017 }
1018 Dart_Handle res = Dart_SetExceptionPauseInfo(info);
1019 ASSERT_NOT_ERROR(res);
1020 dart::TextBuffer msg(32);
1021 msg.Printf("{ \"id\": %d }", msg_id);
1022 in_msg->SendReply(&msg);
1023 return false;
1024 }
1025
1026
1027 bool DbgMessage::HandleRemBpCmd(DbgMessage* in_msg) {
1028 ASSERT(in_msg != NULL);
1029 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
1030 int msg_id = msg_parser.MessageId();
1031 int bpt_id = msg_parser.GetIntParam("breakpointId");
1032 Dart_Handle res = Dart_RemoveBreakpoint(bpt_id);
1033 if (Dart_IsError(res)) {
1034 in_msg->SendErrorReply(msg_id, Dart_GetError(res));
1035 return false;
1036 }
1037 dart::TextBuffer msg(32);
1038 msg.Printf("{ \"id\": %d }", msg_id);
1039 in_msg->SendReply(&msg);
1040 return false;
1041 }
1042
1043
1044 void DbgMsgQueue::AddMessage(int32_t cmd_idx,
1045 const char* start,
1046 const char* end,
1047 intptr_t debug_fd) {
1048 if ((end > start) && ((end - start) < kMaxInt32)) {
1049 MonitorLocker ml(&msg_queue_lock_);
1050 DbgMessage* msg = new DbgMessage(cmd_idx, start, end, debug_fd);
1051 if (msglist_head_ == NULL) {
1052 ASSERT(msglist_tail_ == NULL);
1053 msglist_head_ = msg;
1054 msglist_tail_ = msg;
1055 ml.Notify();
1056 } else {
1057 ASSERT(msglist_tail_ != NULL);
1058 msglist_tail_->set_next(msg);
1059 msglist_tail_ = msg;
1060 }
1061 }
1062 }
1063
1064
1065 void DbgMsgQueue::Notify() {
1066 MonitorLocker ml(&msg_queue_lock_);
1067 ml.Notify();
1068 }
1069
1070
1071 bool DbgMsgQueue::HandlePendingMessages() {
1072 // Handle all available debug messages, up to a resume request.
1073 bool resume_requested = false;
1074 while (msglist_head_ != NULL && !resume_requested) {
1075 ASSERT(msglist_tail_ != NULL);
1076 DbgMessage* msg = msglist_head_;
1077 msglist_head_ = msglist_head_->next();
1078 if (msglist_head_ == NULL) {
1079 msglist_tail_ = NULL;
1080 }
1081 resume_requested = msg->HandleMessage();
1082 delete msg;
1083 }
1084 return resume_requested;
1085 }
1086
1087
1088 void DbgMsgQueue::MessageLoop() {
1089 MonitorLocker ml(&msg_queue_lock_);
1090 is_running_ = false;
1091
1092 // Request notification on isolate messages. This allows us to
1093 // respond to vm service messages while at breakpoint.
1094 Dart_SetMessageNotifyCallback(DbgMsgQueueList::NotifyIsolate);
1095
1096 while (true) {
1097 // Handle all available vm service messages, up to a resume
1098 // request.
1099 bool resume = false;
1100 while (!resume && Dart_HasServiceMessages()) {
1101 msg_queue_lock_.Exit();
1102 resume = Dart_HandleServiceMessages();
1103 msg_queue_lock_.Enter();
1104 }
1105 if (resume) {
1106 break;
1107 }
1108
1109 // Handle all available debug messages, up to a resume request.
1110 if (HandlePendingMessages()) {
1111 break;
1112 }
1113
1114 // Wait for more debug or vm service messages.
1115 Monitor::WaitResult res = ml.Wait();
1116 ASSERT(res == Monitor::kNotified);
1117 }
1118 Dart_SetMessageNotifyCallback(NULL);
1119 is_interrupted_ = false;
1120 is_running_ = true;
1121 }
1122
1123
1124 void DbgMsgQueue::InterruptIsolate() {
1125 Dart_Isolate isolate = Dart_GetIsolate(isolate_id_);
1126 MonitorLocker ml(&msg_queue_lock_);
1127 if (is_running_ && !is_interrupted_) {
1128 is_interrupted_ = true;
1129 Dart_InterruptIsolate(isolate);
1130 }
1131 }
1132
1133
1134 void DbgMsgQueue::QueueOutputMsg(dart::TextBuffer* msg) {
1135 queued_output_messages_.Printf("%s", msg->buf());
1136 }
1137
1138
1139 void DbgMsgQueue::SendQueuedMsgs() {
1140 if (queued_output_messages_.length() > 0) {
1141 DebuggerConnectionHandler::BroadcastMsg(&queued_output_messages_);
1142 queued_output_messages_.Clear();
1143 }
1144 }
1145
1146
1147 void DbgMsgQueue::SendBreakpointEvent(intptr_t bp_id,
1148 const Dart_CodeLocation& location) {
1149 dart::TextBuffer msg(128);
1150 msg.Printf("{ \"event\": \"paused\", \"params\": { ");
1151 msg.Printf("\"reason\": \"breakpoint\", ");
1152 msg.Printf("\"isolateId\": %" Pd64 "", isolate_id_);
1153 if (bp_id != ILLEGAL_BREAKPOINT_ID) {
1154 msg.Printf(",\"breakpointId\": %" Pd "", bp_id);
1155 }
1156 if (!Dart_IsNull(location.script_url)) {
1157 ASSERT(Dart_IsString(location.script_url));
1158 msg.Printf(",\"location\": { \"url\":");
1159 FormatEncodedString(&msg, location.script_url);
1160 msg.Printf(",\"libraryId\":%d,", location.library_id);
1161 msg.Printf("\"tokenOffset\":%d}", location.token_pos);
1162 }
1163 msg.Printf("}}");
1164 DebuggerConnectionHandler::BroadcastMsg(&msg);
1165 }
1166
1167
1168 // TODO(hausner): Remove stack trace parameter once we remove the stack
1169 // trace from the paused event in the wire protocol.
1170 void DbgMsgQueue::SendExceptionEvent(Dart_Handle exception,
1171 Dart_StackTrace stack_trace) {
1172 intptr_t exception_id = Dart_CacheObject(exception);
1173 ASSERT(exception_id >= 0);
1174 dart::TextBuffer msg(128);
1175 msg.Printf("{ \"event\": \"paused\", \"params\": {");
1176 msg.Printf("\"reason\": \"exception\", ");
1177 msg.Printf("\"isolateId\": %" Pd64 ", ", isolate_id_);
1178 msg.Printf("\"exception\":");
1179 FormatRemoteObj(&msg, exception);
1180 FormatLocationFromTrace(&msg, stack_trace, ", ");
1181 msg.Printf("}}");
1182 DebuggerConnectionHandler::BroadcastMsg(&msg);
1183 }
1184
1185
1186 // TODO(hausner): Remove stack trace parameter once we remove the stack
1187 // trace from the interrupted event in the wire protocol.
1188 void DbgMsgQueue::SendIsolateEvent(Dart_IsolateId isolate_id,
1189 Dart_IsolateEvent kind) {
1190 dart::TextBuffer msg(128);
1191 if (kind == kInterrupted) {
1192 Dart_StackTrace trace;
1193 Dart_Handle res = Dart_GetStackTrace(&trace);
1194 ASSERT_NOT_ERROR(res);
1195 msg.Printf("{ \"event\": \"paused\", \"params\": { ");
1196 msg.Printf("\"reason\": \"interrupted\", ");
1197 msg.Printf("\"isolateId\": %" Pd64 "", isolate_id);
1198 FormatLocationFromTrace(&msg, trace, ", ");
1199 msg.Printf("}}");
1200 } else {
1201 msg.Printf("{ \"event\": \"isolate\", \"params\": { ");
1202 if (kind == kCreated) {
1203 msg.Printf("\"reason\": \"created\", ");
1204 } else {
1205 ASSERT(kind == kShutdown);
1206 msg.Printf("\"reason\": \"shutdown\", ");
1207 }
1208 msg.Printf("\"id\": %" Pd64 " ", isolate_id);
1209 msg.Printf("}}");
1210 }
1211 DebuggerConnectionHandler::BroadcastMsg(&msg);
1212 }
1213
1214
1215 DbgMsgQueue* DbgMsgQueueList::list_ = NULL;
1216 Mutex* DbgMsgQueueList::msg_queue_list_lock_ = new Mutex();
1217
1218
1219 void DbgMsgQueueList::Initialize() {
1220 // Setup handlers for isolate events, breakpoints, exceptions and
1221 // delayed breakpoints.
1222 Dart_SetIsolateEventHandler(IsolateEventHandler);
1223 Dart_SetPausedEventHandler(PausedEventHandler);
1224 Dart_SetBreakpointResolvedHandler(BptResolvedHandler);
1225 Dart_SetExceptionThrownHandler(ExceptionThrownHandler);
1226 }
1227
1228
1229 int32_t DbgMsgQueueList::LookupIsolateCommand(const char* buf,
1230 int32_t buflen) {
1231 // Check if we have a isolate specific debugger command.
1232 int32_t i = 0;
1233 while (debugger_commands[i].cmd_string != NULL) {
1234 if (strncmp(buf, debugger_commands[i].cmd_string, buflen) == 0) {
1235 return i;
1236 }
1237 i++;
1238 }
1239 return kInvalidCommand;
1240 }
1241
1242
1243 bool DbgMsgQueueList::AddIsolateMessage(Dart_IsolateId isolate_id,
1244 int32_t cmd_idx,
1245 const char* start,
1246 const char* end,
1247 intptr_t debug_fd) {
1248 MutexLocker ml(msg_queue_list_lock_);
1249 DbgMsgQueue* queue = DbgMsgQueueList::GetIsolateMsgQueueLocked(isolate_id);
1250 if (queue != NULL) {
1251 queue->AddMessage(cmd_idx, start, end, debug_fd);
1252 return true;
1253 }
1254 return false;
1255 }
1256
1257
1258 void DbgMsgQueueList::NotifyIsolate(Dart_Isolate isolate) {
1259 MutexLocker ml(msg_queue_list_lock_);
1260 Dart_IsolateId isolate_id = Dart_GetIsolateId(isolate);
1261 DbgMsgQueue* queue = DbgMsgQueueList::GetIsolateMsgQueueLocked(isolate_id);
1262 if (queue != NULL) {
1263 queue->Notify();
1264 }
1265 }
1266
1267
1268 bool DbgMsgQueueList::InterruptIsolate(Dart_IsolateId isolate_id) {
1269 MutexLocker ml(msg_queue_list_lock_);
1270 DbgMsgQueue* queue = DbgMsgQueueList::GetIsolateMsgQueueLocked(isolate_id);
1271 if (queue != NULL) {
1272 queue->InterruptIsolate();
1273 return true;
1274 }
1275 return false;
1276 }
1277
1278
1279 DbgMsgQueue* DbgMsgQueueList::AddIsolateMsgQueue(Dart_IsolateId isolate_id) {
1280 MutexLocker ml(msg_queue_list_lock_);
1281
1282 DbgMsgQueue* queue = new DbgMsgQueue(isolate_id, list_);
1283 ASSERT(queue != NULL);
1284 list_ = queue;
1285 return queue;
1286 }
1287
1288
1289 DbgMsgQueue* DbgMsgQueueList::GetIsolateMsgQueue(Dart_IsolateId isolate_id) {
1290 MutexLocker ml(msg_queue_list_lock_);
1291 ASSERT(Dart_GetIsolate(isolate_id) == Dart_CurrentIsolate());
1292 return GetIsolateMsgQueueLocked(isolate_id);
1293 }
1294
1295
1296 DbgMsgQueue* DbgMsgQueueList::GetIsolateMsgQueueLocked(Dart_IsolateId id) {
1297 if (list_ == NULL) {
1298 return NULL; // No items in the list.
1299 }
1300
1301 // Find message queue corresponding to isolate id.
1302 DbgMsgQueue* iterator = list_;
1303 while (iterator != NULL && iterator->isolate_id() != id) {
1304 iterator = iterator->next();
1305 }
1306 return iterator;
1307 }
1308
1309
1310 void DbgMsgQueueList::RemoveIsolateMsgQueue(Dart_IsolateId isolate_id) {
1311 MutexLocker ml(msg_queue_list_lock_);
1312 if (list_ == NULL) {
1313 return; // No items in the list.
1314 }
1315 DbgMsgQueue* queue = list_;
1316 if (queue->isolate_id() == isolate_id) {
1317 list_ = queue->next(); // Remove from list.
1318 delete queue; // Delete the message queue.
1319 return;
1320 } else {
1321 DbgMsgQueue* iterator = queue;
1322 queue = queue->next();
1323 while (queue != NULL) {
1324 if (queue->isolate_id() == isolate_id) {
1325 iterator->set_next(queue->next()); // Remove from list.
1326 delete queue; // Delete the message queue.
1327 return;
1328 }
1329 iterator = queue;
1330 queue = queue->next();
1331 }
1332 }
1333 UNREACHABLE();
1334 }
1335
1336
1337 void DbgMsgQueueList::ListIsolateIds(dart::TextBuffer* msg) {
1338 MutexLocker ml(msg_queue_list_lock_);
1339 if (list_ == NULL) {
1340 return; // No items in the list.
1341 }
1342 DbgMsgQueue* queue = list_;
1343 msg->Printf("%" Pd64 "", queue->isolate_id());
1344 queue = queue->next();
1345 while (queue != NULL) {
1346 msg->Printf(",%" Pd64 "", queue->isolate_id());
1347 queue = queue->next();
1348 }
1349 }
1350
1351
1352 void DbgMsgQueueList::BptResolvedHandler(Dart_IsolateId isolate_id,
1353 intptr_t bp_id,
1354 const Dart_CodeLocation& location) {
1355 Dart_EnterScope();
1356 dart::TextBuffer msg(128);
1357 msg.Printf("{ \"event\": \"breakpointResolved\", \"params\": {");
1358 msg.Printf("\"breakpointId\": %" Pd "", bp_id);
1359
1360 msg.Printf(", \"isolateId\":%" Pd64 "", isolate_id);
1361 ASSERT(!Dart_IsNull(location.script_url));
1362 ASSERT(Dart_IsString(location.script_url));
1363 msg.Printf(", \"location\":{\"url\":");
1364 FormatEncodedString(&msg, location.script_url);
1365 msg.Printf(",\"libraryId\":%d", location.library_id);
1366 msg.Printf(",\"tokenOffset\":%d}}}", location.token_pos);
1367
1368 DbgMsgQueue* msg_queue = GetIsolateMsgQueue(isolate_id);
1369 ASSERT(msg_queue != NULL);
1370 msg_queue->QueueOutputMsg(&msg);
1371 Dart_ExitScope();
1372 }
1373
1374
1375 void DbgMsgQueueList::PausedEventHandler(Dart_IsolateId isolate_id,
1376 intptr_t bp_id,
1377 const Dart_CodeLocation& loc) {
1378 DebuggerConnectionHandler::WaitForConnection();
1379 Dart_EnterScope();
1380 DbgMsgQueue* msg_queue = GetIsolateMsgQueue(isolate_id);
1381 ASSERT(msg_queue != NULL);
1382 msg_queue->SendQueuedMsgs();
1383 msg_queue->SendBreakpointEvent(bp_id, loc);
1384 msg_queue->MessageLoop();
1385 Dart_ExitScope();
1386 }
1387
1388
1389 void DbgMsgQueueList::ExceptionThrownHandler(Dart_IsolateId isolate_id,
1390 Dart_Handle exception,
1391 Dart_StackTrace stack_trace) {
1392 DebuggerConnectionHandler::WaitForConnection();
1393 Dart_EnterScope();
1394 DbgMsgQueue* msg_queue = GetIsolateMsgQueue(isolate_id);
1395 ASSERT(msg_queue != NULL);
1396 msg_queue->SendQueuedMsgs();
1397 msg_queue->SendExceptionEvent(exception, stack_trace);
1398 msg_queue->MessageLoop();
1399 Dart_ExitScope();
1400 }
1401
1402
1403 void DbgMsgQueueList::IsolateEventHandler(Dart_IsolateId isolate_id,
1404 Dart_IsolateEvent kind) {
1405 if (kind == kCreated) {
1406 DebuggerConnectionHandler::WaitForConnection();
1407 Dart_EnterScope();
1408 DbgMsgQueue* msg_queue = AddIsolateMsgQueue(isolate_id);
1409 msg_queue->SendIsolateEvent(isolate_id, kind);
1410 Dart_ExitScope();
1411 } else {
1412 DebuggerConnectionHandler::WaitForConnection();
1413 DbgMsgQueue* msg_queue = GetIsolateMsgQueue(isolate_id);
1414 ASSERT(msg_queue != NULL);
1415 Dart_EnterScope();
1416 msg_queue->SendQueuedMsgs();
1417 msg_queue->SendIsolateEvent(isolate_id, kind);
1418 if (kind == kInterrupted) {
1419 msg_queue->MessageLoop();
1420 } else {
1421 ASSERT(kind == kShutdown);
1422 RemoveIsolateMsgQueue(isolate_id);
1423 }
1424 Dart_ExitScope();
1425 // If there is no receive message queue, do not wait for a connection, and
1426 // ignore the message.
1427 }
1428 }
1429
1430 } // namespace bin
1431 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/bin/dbg_message.h ('k') | runtime/bin/main.cc » ('j') | runtime/bin/main.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698