| 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 "vm/debugger.h" | 5 #include "vm/debugger.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 | 8 |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
| 11 #include "vm/compiler.h" | 11 #include "vm/compiler.h" |
| 12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
| 13 #include "vm/deopt_instructions.h" | 13 #include "vm/deopt_instructions.h" |
| 14 #include "vm/flags.h" | 14 #include "vm/flags.h" |
| 15 #include "vm/globals.h" | 15 #include "vm/globals.h" |
| 16 #include "vm/longjump.h" | 16 #include "vm/longjump.h" |
| 17 #include "vm/json_stream.h" | 17 #include "vm/json_stream.h" |
| 18 #include "vm/object.h" | 18 #include "vm/object.h" |
| 19 #include "vm/object_store.h" | 19 #include "vm/object_store.h" |
| 20 #include "vm/os.h" | 20 #include "vm/os.h" |
| 21 #include "vm/port.h" | 21 #include "vm/port.h" |
| 22 #include "vm/service.h" |
| 22 #include "vm/stack_frame.h" | 23 #include "vm/stack_frame.h" |
| 23 #include "vm/stub_code.h" | 24 #include "vm/stub_code.h" |
| 24 #include "vm/symbols.h" | 25 #include "vm/symbols.h" |
| 25 #include "vm/visitor.h" | 26 #include "vm/visitor.h" |
| 26 | 27 |
| 27 | 28 |
| 28 namespace dart { | 29 namespace dart { |
| 29 | 30 |
| 30 DEFINE_FLAG(bool, enable_debugger, true, "Enables debugger step checks"); | 31 DEFINE_FLAG(bool, enable_debugger, true, "Enables debugger step checks"); |
| 31 DEFINE_FLAG(bool, show_invisible_frames, false, | 32 DEFINE_FLAG(bool, show_invisible_frames, false, |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 context_level_(-1), | 186 context_level_(-1), |
| 186 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), | 187 deopt_frame_(Array::ZoneHandle(deopt_frame.raw())), |
| 187 deopt_frame_offset_(deopt_frame_offset), | 188 deopt_frame_offset_(deopt_frame_offset), |
| 188 vars_initialized_(false), | 189 vars_initialized_(false), |
| 189 var_descriptors_(LocalVarDescriptors::ZoneHandle()), | 190 var_descriptors_(LocalVarDescriptors::ZoneHandle()), |
| 190 desc_indices_(8), | 191 desc_indices_(8), |
| 191 pc_desc_(PcDescriptors::ZoneHandle()) { | 192 pc_desc_(PcDescriptors::ZoneHandle()) { |
| 192 } | 193 } |
| 193 | 194 |
| 194 | 195 |
| 196 bool Debugger::HasEventHandler() { |
| 197 return (event_handler_ != NULL) || Service::NeedsDebuggerEvents(); |
| 198 } |
| 199 |
| 200 |
| 201 void Debugger::InvokeEventHandler(DebuggerEvent* event) { |
| 202 ASSERT(HasEventHandler()); |
| 203 |
| 204 // Give the event to the Service first, as the debugger event handler |
| 205 // may go into a message loop and the Service will not. |
| 206 if (Service::NeedsDebuggerEvents()) { |
| 207 Service::HandleDebuggerEvent(event); |
| 208 } |
| 209 |
| 210 if (event_handler_ != NULL) { |
| 211 (*event_handler_)(event); |
| 212 } |
| 213 } |
| 214 |
| 215 |
| 195 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { | 216 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { |
| 196 if (event_handler_ != NULL) { | 217 if (HasEventHandler()) { |
| 197 DebuggerEvent event(type); | 218 DebuggerEvent event(isolate_, type); |
| 198 event.set_isolate_id(isolate_id_); | |
| 199 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); | 219 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); |
| 200 if (type == DebuggerEvent::kIsolateInterrupted) { | 220 if (type == DebuggerEvent::kIsolateInterrupted) { |
| 201 DebuggerStackTrace* trace = CollectStackTrace(); | 221 DebuggerStackTrace* trace = CollectStackTrace(); |
| 202 ASSERT(trace->Length() > 0); | 222 ASSERT(trace->Length() > 0); |
| 203 ASSERT(stack_trace_ == NULL); | 223 ASSERT(stack_trace_ == NULL); |
| 204 stack_trace_ = trace; | 224 stack_trace_ = trace; |
| 205 resume_action_ = kContinue; | 225 resume_action_ = kContinue; |
| 206 Pause(&event); | 226 Pause(&event); |
| 207 HandleSteppingRequest(trace); | 227 HandleSteppingRequest(trace); |
| 208 stack_trace_ = NULL; | 228 stack_trace_ = NULL; |
| 209 } else { | 229 } else { |
| 210 (*event_handler_)(&event); | 230 InvokeEventHandler(&event); |
| 211 } | 231 } |
| 212 } | 232 } |
| 213 } | 233 } |
| 214 | 234 |
| 215 | 235 |
| 216 void Debugger::SignalIsolateInterrupted() { | 236 void Debugger::SignalIsolateInterrupted() { |
| 217 if (event_handler_ != NULL) { | 237 if (HasEventHandler()) { |
| 218 Debugger* debugger = Isolate::Current()->debugger(); | 238 Debugger* debugger = Isolate::Current()->debugger(); |
| 219 ASSERT(debugger != NULL); | 239 ASSERT(debugger != NULL); |
| 220 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); | 240 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); |
| 221 } | 241 } |
| 222 } | 242 } |
| 223 | 243 |
| 224 | 244 |
| 225 const char* Debugger::QualifiedFunctionName(const Function& func) { | 245 const char* Debugger::QualifiedFunctionName(const Function& func) { |
| 226 const String& func_name = String::Handle(func.name()); | 246 const String& func_name = String::Handle(func.name()); |
| 227 Class& func_class = Class::Handle(func.Owner()); | 247 Class& func_class = Class::Handle(func.Owner()); |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 return "IsolateInterrupted"; | 523 return "IsolateInterrupted"; |
| 504 default: | 524 default: |
| 505 UNREACHABLE(); | 525 UNREACHABLE(); |
| 506 return "Unknown"; | 526 return "Unknown"; |
| 507 } | 527 } |
| 508 } | 528 } |
| 509 | 529 |
| 510 | 530 |
| 511 void DebuggerEvent::PrintJSON(JSONStream* js) const { | 531 void DebuggerEvent::PrintJSON(JSONStream* js) const { |
| 512 JSONObject jsobj(js); | 532 JSONObject jsobj(js); |
| 513 jsobj.AddProperty("type", "DebuggerEvent"); | 533 jsobj.AddProperty("type", "ServiceEvent"); |
| 514 // TODO(turnidge): Drop the 'id' for things like DebuggerEvent. | 534 // TODO(turnidge): Drop the 'id' for things like DebuggerEvent. |
| 515 jsobj.AddProperty("id", ""); | 535 jsobj.AddProperty("id", ""); |
| 516 // TODO(turnidge): Add 'isolate'. | |
| 517 jsobj.AddProperty("eventType", EventTypeToCString(type())); | 536 jsobj.AddProperty("eventType", EventTypeToCString(type())); |
| 537 jsobj.AddProperty("isolate", isolate()); |
| 518 if (type() == kBreakpointResolved || type() == kBreakpointReached) { | 538 if (type() == kBreakpointResolved || type() == kBreakpointReached) { |
| 519 jsobj.AddProperty("breakpoint", breakpoint()); | 539 jsobj.AddProperty("breakpoint", breakpoint()); |
| 520 } | 540 } |
| 521 if (type() == kExceptionThrown) { | 541 if (type() == kExceptionThrown) { |
| 522 jsobj.AddProperty("exception", *(exception())); | 542 jsobj.AddProperty("exception", *(exception())); |
| 523 } | 543 } |
| 524 } | 544 } |
| 525 | 545 |
| 526 | 546 |
| 527 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( | 547 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( |
| (...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1205 } | 1225 } |
| 1206 bpt = new CodeBreakpoint(code, i); | 1226 bpt = new CodeBreakpoint(code, i); |
| 1207 RegisterCodeBreakpoint(bpt); | 1227 RegisterCodeBreakpoint(bpt); |
| 1208 bpt->Enable(); | 1228 bpt->Enable(); |
| 1209 } | 1229 } |
| 1210 } | 1230 } |
| 1211 } | 1231 } |
| 1212 | 1232 |
| 1213 | 1233 |
| 1214 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { | 1234 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { |
| 1215 if (event_handler_ != NULL) { | 1235 if (HasEventHandler()) { |
| 1216 DebuggerEvent event(DebuggerEvent::kBreakpointResolved); | 1236 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved); |
| 1217 event.set_breakpoint(bpt); | 1237 event.set_breakpoint(bpt); |
| 1218 (*event_handler_)(&event); | 1238 InvokeEventHandler(&event); |
| 1219 } | 1239 } |
| 1220 } | 1240 } |
| 1221 | 1241 |
| 1222 | 1242 |
| 1223 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, | 1243 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, |
| 1224 uword pc, | 1244 uword pc, |
| 1225 StackFrame* frame, | 1245 StackFrame* frame, |
| 1226 const Code& code, | 1246 const Code& code, |
| 1227 const Array& deopt_frame, | 1247 const Array& deopt_frame, |
| 1228 intptr_t deopt_frame_offset, | 1248 intptr_t deopt_frame_offset, |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1493 } | 1513 } |
| 1494 | 1514 |
| 1495 | 1515 |
| 1496 void Debugger::SignalExceptionThrown(const Instance& exc) { | 1516 void Debugger::SignalExceptionThrown(const Instance& exc) { |
| 1497 // We ignore this exception event when the VM is executing code invoked | 1517 // We ignore this exception event when the VM is executing code invoked |
| 1498 // by the debugger to evaluate variables values, when we see a nested | 1518 // by the debugger to evaluate variables values, when we see a nested |
| 1499 // breakpoint or exception event, or if the debugger is not | 1519 // breakpoint or exception event, or if the debugger is not |
| 1500 // interested in exception events. | 1520 // interested in exception events. |
| 1501 if (ignore_breakpoints_ || | 1521 if (ignore_breakpoints_ || |
| 1502 IsPaused() || | 1522 IsPaused() || |
| 1503 (event_handler_ == NULL) || | 1523 (!HasEventHandler()) || |
| 1504 (exc_pause_info_ == kNoPauseOnExceptions)) { | 1524 (exc_pause_info_ == kNoPauseOnExceptions)) { |
| 1505 return; | 1525 return; |
| 1506 } | 1526 } |
| 1507 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 1527 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
| 1508 if (!ShouldPauseOnException(stack_trace, exc)) { | 1528 if (!ShouldPauseOnException(stack_trace, exc)) { |
| 1509 return; | 1529 return; |
| 1510 } | 1530 } |
| 1511 DebuggerEvent event(DebuggerEvent::kExceptionThrown); | 1531 DebuggerEvent event(isolate_, DebuggerEvent::kExceptionThrown); |
| 1512 event.set_exception(&exc); | 1532 event.set_exception(&exc); |
| 1513 ASSERT(stack_trace_ == NULL); | 1533 ASSERT(stack_trace_ == NULL); |
| 1514 stack_trace_ = stack_trace; | 1534 stack_trace_ = stack_trace; |
| 1515 Pause(&event); | 1535 Pause(&event); |
| 1516 stack_trace_ = NULL; | 1536 stack_trace_ = NULL; |
| 1517 } | 1537 } |
| 1518 | 1538 |
| 1519 | 1539 |
| 1520 // Given a function and a token range, return the best fit | 1540 // Given a function and a token range, return the best fit |
| 1521 // token position to set a breakpoint. The best fit is the safe point | 1541 // token position to set a breakpoint. The best fit is the safe point |
| (...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2131 prefix_name = String::Concat(prefix_name, Symbols::Dot()); | 2151 prefix_name = String::Concat(prefix_name, Symbols::Dot()); |
| 2132 for (intptr_t i = 0; i < prefix.num_imports(); i++) { | 2152 for (intptr_t i = 0; i < prefix.num_imports(); i++) { |
| 2133 imported = prefix.GetLibrary(i); | 2153 imported = prefix.GetLibrary(i); |
| 2134 CollectLibraryFields(field_list, imported, prefix_name, false); | 2154 CollectLibraryFields(field_list, imported, prefix_name, false); |
| 2135 } | 2155 } |
| 2136 } | 2156 } |
| 2137 return Array::MakeArray(field_list); | 2157 return Array::MakeArray(field_list); |
| 2138 } | 2158 } |
| 2139 | 2159 |
| 2140 | 2160 |
| 2161 // static |
| 2141 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 2162 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 2142 ASSERT(visitor != NULL); | 2163 ASSERT(visitor != NULL); |
| 2143 SourceBreakpoint* bpt = src_breakpoints_; | 2164 SourceBreakpoint* bpt = src_breakpoints_; |
| 2144 while (bpt != NULL) { | 2165 while (bpt != NULL) { |
| 2145 bpt->VisitObjectPointers(visitor); | 2166 bpt->VisitObjectPointers(visitor); |
| 2146 bpt = bpt->next(); | 2167 bpt = bpt->next(); |
| 2147 } | 2168 } |
| 2148 CodeBreakpoint* cbpt = code_breakpoints_; | 2169 CodeBreakpoint* cbpt = code_breakpoints_; |
| 2149 while (cbpt != NULL) { | 2170 while (cbpt != NULL) { |
| 2150 cbpt->VisitObjectPointers(visitor); | 2171 cbpt->VisitObjectPointers(visitor); |
| 2151 cbpt = cbpt->next(); | 2172 cbpt = cbpt->next(); |
| 2152 } | 2173 } |
| 2153 } | 2174 } |
| 2154 | 2175 |
| 2155 | 2176 |
| 2177 // static |
| 2156 void Debugger::SetEventHandler(EventHandler* handler) { | 2178 void Debugger::SetEventHandler(EventHandler* handler) { |
| 2157 event_handler_ = handler; | 2179 event_handler_ = handler; |
| 2158 } | 2180 } |
| 2159 | 2181 |
| 2160 | 2182 |
| 2161 void Debugger::Pause(DebuggerEvent* event) { | 2183 void Debugger::Pause(DebuggerEvent* event) { |
| 2162 ASSERT(!IsPaused()); // No recursive pausing. | 2184 ASSERT(!IsPaused()); // No recursive pausing. |
| 2163 ASSERT(obj_cache_ == NULL); | 2185 ASSERT(obj_cache_ == NULL); |
| 2164 | 2186 |
| 2165 pause_event_ = event; | 2187 pause_event_ = event; |
| 2166 obj_cache_ = new RemoteObjectCache(64); | 2188 obj_cache_ = new RemoteObjectCache(64); |
| 2167 | 2189 |
| 2168 (*event_handler_)(event); | 2190 InvokeEventHandler(event); |
| 2169 | 2191 |
| 2170 pause_event_ = NULL; | 2192 pause_event_ = NULL; |
| 2171 obj_cache_ = NULL; // Zone allocated | 2193 obj_cache_ = NULL; // Zone allocated |
| 2172 } | 2194 } |
| 2173 | 2195 |
| 2174 | 2196 |
| 2175 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace) { | 2197 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace) { |
| 2176 stepping_fp_ = 0; | 2198 stepping_fp_ = 0; |
| 2177 if (resume_action_ == kSingleStep) { | 2199 if (resume_action_ == kSingleStep) { |
| 2178 isolate_->set_single_step(true); | 2200 isolate_->set_single_step(true); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2205 } | 2227 } |
| 2206 | 2228 |
| 2207 | 2229 |
| 2208 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, | 2230 void Debugger::SignalPausedEvent(ActivationFrame* top_frame, |
| 2209 SourceBreakpoint* bpt) { | 2231 SourceBreakpoint* bpt) { |
| 2210 resume_action_ = kContinue; | 2232 resume_action_ = kContinue; |
| 2211 stepping_fp_ = 0; | 2233 stepping_fp_ = 0; |
| 2212 isolate_->set_single_step(false); | 2234 isolate_->set_single_step(false); |
| 2213 ASSERT(!IsPaused()); | 2235 ASSERT(!IsPaused()); |
| 2214 ASSERT(obj_cache_ == NULL); | 2236 ASSERT(obj_cache_ == NULL); |
| 2215 DebuggerEvent event(DebuggerEvent::kBreakpointReached); | 2237 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached); |
| 2216 event.set_top_frame(top_frame); | 2238 event.set_top_frame(top_frame); |
| 2217 event.set_breakpoint(bpt); | 2239 event.set_breakpoint(bpt); |
| 2218 Pause(&event); | 2240 Pause(&event); |
| 2219 } | 2241 } |
| 2220 | 2242 |
| 2221 | 2243 |
| 2222 void Debugger::DebuggerStepCallback() { | 2244 void Debugger::DebuggerStepCallback() { |
| 2223 ASSERT(isolate_->single_step()); | 2245 ASSERT(isolate_->single_step()); |
| 2224 // We can't get here unless the debugger event handler enabled | 2246 // We can't get here unless the debugger event handler enabled |
| 2225 // single stepping. | 2247 // single stepping. |
| 2226 ASSERT(event_handler_ != NULL); | 2248 ASSERT(HasEventHandler()); |
| 2227 // Don't pause recursively. | 2249 // Don't pause recursively. |
| 2228 if (IsPaused()) return; | 2250 if (IsPaused()) return; |
| 2229 | 2251 |
| 2230 // Check whether we are in a Dart function that the user is | 2252 // Check whether we are in a Dart function that the user is |
| 2231 // interested in. If we saved the frame pointer of a stack frame | 2253 // interested in. If we saved the frame pointer of a stack frame |
| 2232 // the user is interested in, we ignore the single step if we are | 2254 // the user is interested in, we ignore the single step if we are |
| 2233 // in a callee of that frame. Note that we assume that the stack | 2255 // in a callee of that frame. Note that we assume that the stack |
| 2234 // grows towards lower addresses. | 2256 // grows towards lower addresses. |
| 2235 ActivationFrame* frame = TopDartFrame(); | 2257 ActivationFrame* frame = TopDartFrame(); |
| 2236 ASSERT(frame != NULL); | 2258 ASSERT(frame != NULL); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2276 SignalPausedEvent(frame, NULL); | 2298 SignalPausedEvent(frame, NULL); |
| 2277 HandleSteppingRequest(stack_trace_); | 2299 HandleSteppingRequest(stack_trace_); |
| 2278 stack_trace_ = NULL; | 2300 stack_trace_ = NULL; |
| 2279 } | 2301 } |
| 2280 | 2302 |
| 2281 | 2303 |
| 2282 void Debugger::SignalBpReached() { | 2304 void Debugger::SignalBpReached() { |
| 2283 // We ignore this breakpoint when the VM is executing code invoked | 2305 // We ignore this breakpoint when the VM is executing code invoked |
| 2284 // by the debugger to evaluate variables values, or when we see a nested | 2306 // by the debugger to evaluate variables values, or when we see a nested |
| 2285 // breakpoint or exception event. | 2307 // breakpoint or exception event. |
| 2286 if (ignore_breakpoints_ || IsPaused() || (event_handler_ == NULL)) { | 2308 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { |
| 2287 return; | 2309 return; |
| 2288 } | 2310 } |
| 2289 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 2311 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
| 2290 ASSERT(stack_trace->Length() > 0); | 2312 ASSERT(stack_trace->Length() > 0); |
| 2291 ActivationFrame* top_frame = stack_trace->FrameAt(0); | 2313 ActivationFrame* top_frame = stack_trace->FrameAt(0); |
| 2292 ASSERT(top_frame != NULL); | 2314 ASSERT(top_frame != NULL); |
| 2293 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc()); | 2315 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc()); |
| 2294 ASSERT(bpt != NULL); | 2316 ASSERT(bpt != NULL); |
| 2295 | 2317 |
| 2296 if (FLAG_verbose_debug) { | 2318 if (FLAG_verbose_debug) { |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2562 } | 2584 } |
| 2563 | 2585 |
| 2564 | 2586 |
| 2565 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2587 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 2566 ASSERT(bpt->next() == NULL); | 2588 ASSERT(bpt->next() == NULL); |
| 2567 bpt->set_next(code_breakpoints_); | 2589 bpt->set_next(code_breakpoints_); |
| 2568 code_breakpoints_ = bpt; | 2590 code_breakpoints_ = bpt; |
| 2569 } | 2591 } |
| 2570 | 2592 |
| 2571 } // namespace dart | 2593 } // namespace dart |
| OLD | NEW |