Chromium Code Reviews| 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" |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 581 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { | 581 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { |
| 582 trace_.Add(frame); | 582 trace_.Add(frame); |
| 583 } | 583 } |
| 584 | 584 |
| 585 | 585 |
| 586 static bool IsSafePoint(PcDescriptors::Kind kind) { | 586 static bool IsSafePoint(PcDescriptors::Kind kind) { |
| 587 return ((kind == PcDescriptors::kIcCall) || | 587 return ((kind == PcDescriptors::kIcCall) || |
| 588 (kind == PcDescriptors::kFuncCall) || | 588 (kind == PcDescriptors::kFuncCall) || |
| 589 (kind == PcDescriptors::kClosureCall) || | 589 (kind == PcDescriptors::kClosureCall) || |
| 590 (kind == PcDescriptors::kReturn) || | 590 (kind == PcDescriptors::kReturn) || |
| 591 (kind == PcDescriptors::kEqualNull)); | 591 (kind == PcDescriptors::kRuntimeCall)); |
| 592 } | 592 } |
| 593 | 593 |
| 594 | 594 |
| 595 CodeBreakpoint::CodeBreakpoint(const Function& func, intptr_t pc_desc_index) | 595 CodeBreakpoint::CodeBreakpoint(const Function& func, intptr_t pc_desc_index) |
| 596 : function_(func.raw()), | 596 : function_(func.raw()), |
| 597 pc_desc_index_(pc_desc_index), | 597 pc_desc_index_(pc_desc_index), |
| 598 pc_(0), | 598 pc_(0), |
| 599 line_number_(-1), | 599 line_number_(-1), |
| 600 is_enabled_(false), | 600 is_enabled_(false), |
| 601 src_bpt_(NULL), | 601 src_bpt_(NULL), |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 665 } | 665 } |
| 666 case PcDescriptors::kFuncCall: { | 666 case PcDescriptors::kFuncCall: { |
| 667 const Code& code = | 667 const Code& code = |
| 668 Code::Handle(Function::Handle(function_).unoptimized_code()); | 668 Code::Handle(Function::Handle(function_).unoptimized_code()); |
| 669 saved_bytes_.target_address_ = | 669 saved_bytes_.target_address_ = |
| 670 CodePatcher::GetStaticCallTargetAt(pc_, code); | 670 CodePatcher::GetStaticCallTargetAt(pc_, code); |
| 671 CodePatcher::PatchStaticCallAt(pc_, code, | 671 CodePatcher::PatchStaticCallAt(pc_, code, |
| 672 StubCode::BreakpointStaticEntryPoint()); | 672 StubCode::BreakpointStaticEntryPoint()); |
| 673 break; | 673 break; |
| 674 } | 674 } |
| 675 case PcDescriptors::kRuntimeCall: | |
| 675 case PcDescriptors::kClosureCall: { | 676 case PcDescriptors::kClosureCall: { |
| 676 const Code& code = | 677 const Code& code = |
| 677 Code::Handle(Function::Handle(function_).unoptimized_code()); | 678 Code::Handle(Function::Handle(function_).unoptimized_code()); |
| 678 saved_bytes_.target_address_ = | 679 saved_bytes_.target_address_ = |
| 679 CodePatcher::GetStaticCallTargetAt(pc_, code); | 680 CodePatcher::GetStaticCallTargetAt(pc_, code); |
| 680 CodePatcher::PatchStaticCallAt(pc_, code, | 681 CodePatcher::PatchStaticCallAt(pc_, code, |
| 681 StubCode::BreakpointClosureEntryPoint()); | 682 StubCode::BreakpointRuntimeEntryPoint()); |
| 682 break; | |
| 683 } | |
| 684 case PcDescriptors::kEqualNull: { | |
| 685 const Code& code = | |
| 686 Code::Handle(Function::Handle(function_).unoptimized_code()); | |
| 687 saved_bytes_.target_address_ = | |
| 688 CodePatcher::GetStaticCallTargetAt(pc_, code); | |
| 689 CodePatcher::PatchStaticCallAt(pc_, code, | |
| 690 StubCode::BreakpointEqNullEntryPoint()); | |
| 691 break; | 683 break; |
| 692 } | 684 } |
| 693 case PcDescriptors::kReturn: | 685 case PcDescriptors::kReturn: |
| 694 PatchFunctionReturn(); | 686 PatchFunctionReturn(); |
| 695 break; | 687 break; |
| 696 default: | 688 default: |
| 697 UNREACHABLE(); | 689 UNREACHABLE(); |
| 698 } | 690 } |
| 699 is_enabled_ = true; | 691 is_enabled_ = true; |
| 700 } | 692 } |
| 701 | 693 |
| 702 | 694 |
| 703 void CodeBreakpoint::RestoreCode() { | 695 void CodeBreakpoint::RestoreCode() { |
| 704 ASSERT(is_enabled_); | 696 ASSERT(is_enabled_); |
| 705 switch (breakpoint_kind_) { | 697 switch (breakpoint_kind_) { |
| 706 case PcDescriptors::kIcCall: { | 698 case PcDescriptors::kIcCall: { |
| 707 const Code& code = | 699 const Code& code = |
| 708 Code::Handle(Function::Handle(function_).unoptimized_code()); | 700 Code::Handle(Function::Handle(function_).unoptimized_code()); |
| 709 CodePatcher::PatchInstanceCallAt(pc_, code, | 701 CodePatcher::PatchInstanceCallAt(pc_, code, |
| 710 saved_bytes_.target_address_); | 702 saved_bytes_.target_address_); |
| 711 break; | 703 break; |
| 712 } | 704 } |
| 713 case PcDescriptors::kFuncCall: | 705 case PcDescriptors::kFuncCall: |
| 714 case PcDescriptors::kClosureCall: | 706 case PcDescriptors::kClosureCall: |
| 715 case PcDescriptors::kEqualNull: { | 707 case PcDescriptors::kRuntimeCall: { |
| 716 const Code& code = | 708 const Code& code = |
| 717 Code::Handle(Function::Handle(function_).unoptimized_code()); | 709 Code::Handle(Function::Handle(function_).unoptimized_code()); |
| 718 CodePatcher::PatchStaticCallAt(pc_, code, | 710 CodePatcher::PatchStaticCallAt(pc_, code, |
| 719 saved_bytes_.target_address_); | 711 saved_bytes_.target_address_); |
| 720 break; | 712 break; |
| 721 } | 713 } |
| 722 case PcDescriptors::kReturn: | 714 case PcDescriptors::kReturn: |
| 723 RestoreFunctionReturn(); | 715 RestoreFunctionReturn(); |
| 724 break; | 716 break; |
| 725 default: | 717 default: |
| (...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1611 Function& closure_func = | 1603 Function& closure_func = |
| 1612 Function::Handle(Closure::function(Instance::Cast(receiver))); | 1604 Function::Handle(Closure::function(Instance::Cast(receiver))); |
| 1613 if (IsDebuggable(closure_func)) { | 1605 if (IsDebuggable(closure_func)) { |
| 1614 func_to_instrument = closure_func.raw(); | 1606 func_to_instrument = closure_func.raw(); |
| 1615 } | 1607 } |
| 1616 } | 1608 } |
| 1617 // If the receiver is not a closure, then the runtime will attempt | 1609 // If the receiver is not a closure, then the runtime will attempt |
| 1618 // to invoke the "call" method on the object if one exists. | 1610 // to invoke the "call" method on the object if one exists. |
| 1619 // TODO(hausner): find call method and intrument it for stepping. | 1611 // TODO(hausner): find call method and intrument it for stepping. |
| 1620 } | 1612 } |
| 1621 } else if (bpt->breakpoint_kind_ == PcDescriptors::kEqualNull) { | 1613 } else if (bpt->breakpoint_kind_ == PcDescriptors::kRuntimeCall) { |
| 1622 // This is just a call to the runtime, not Dart code. Stepping | 1614 // This is just a call to the runtime, not Dart code. Stepping |
| 1623 // into not possible, just treat like StepOver. | 1615 // into not possible, just treat like StepOver. |
| 1624 func_to_instrument = bpt->function(); | 1616 func_to_instrument = bpt->function(); |
| 1625 } else { | 1617 } else { |
| 1626 ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn); | 1618 ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn); |
| 1627 // Treat like stepping out to caller. | 1619 // Treat like stepping out to caller. |
| 1628 if (stack_trace->Length() > 1) { | 1620 if (stack_trace->Length() > 1) { |
| 1629 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1); | 1621 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1); |
| 1630 func_to_instrument = caller_frame->function().raw(); | 1622 func_to_instrument = caller_frame->function().raw(); |
| 1631 } | 1623 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1693 if (FLAG_verbose_debug) { | 1685 if (FLAG_verbose_debug) { |
| 1694 OS::Print("Resetting pending breakpoint to function %s\n", | 1686 OS::Print("Resetting pending breakpoint to function %s\n", |
| 1695 closure.ToFullyQualifiedCString()); | 1687 closure.ToFullyQualifiedCString()); |
| 1696 } | 1688 } |
| 1697 bpt->set_function(closure); | 1689 bpt->set_function(closure); |
| 1698 } else { | 1690 } else { |
| 1699 if (FLAG_verbose_debug) { | 1691 if (FLAG_verbose_debug) { |
| 1700 OS::Print("Enable pending breakpoint for function '%s'\n", | 1692 OS::Print("Enable pending breakpoint for function '%s'\n", |
| 1701 String::Handle(lookup_function.name()).ToCString()); | 1693 String::Handle(lookup_function.name()).ToCString()); |
| 1702 } | 1694 } |
| 1695 const Script& script= Script::Handle(func.script()); | |
| 1696 intptr_t first_pos, last_pos; | |
| 1697 script.TokenRangeAtLine(bpt->LineNumber(), &first_pos, &last_pos); | |
| 1703 intptr_t bp_pos = | 1698 intptr_t bp_pos = |
| 1704 ResolveBreakpointPos(func, bpt->token_pos(), func.end_token_pos()); | 1699 ResolveBreakpointPos(func, bpt->token_pos(), last_pos); |
| 1705 bpt->set_token_pos(bp_pos); | 1700 bpt->set_token_pos(bp_pos); |
| 1706 MakeCodeBreakpointsAt(func, bp_pos, bpt); | 1701 MakeCodeBreakpointsAt(func, bp_pos, bpt); |
| 1707 SignalBpResolved(bpt); | 1702 SignalBpResolved(bpt); |
| 1708 } | 1703 } |
| 1709 bpt->Enable(); // Enables the code breakpoint as well. | 1704 bpt->Enable(); // Enables the code breakpoint as well. |
| 1710 } | 1705 } |
| 1711 bpt = bpt->next(); | 1706 bpt = bpt->next(); |
| 1712 } | 1707 } |
| 1713 } | 1708 } |
| 1714 | 1709 |
| 1715 | 1710 |
| 1716 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) { | 1711 CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) { |
| 1717 CodeBreakpoint* bpt = code_breakpoints_; | 1712 CodeBreakpoint* bpt = code_breakpoints_; |
| 1718 while (bpt != NULL) { | 1713 while (bpt != NULL) { |
| 1719 if (bpt->pc() == breakpoint_address) { | 1714 if (bpt->pc() == breakpoint_address) { |
| 1720 return bpt; | 1715 return bpt; |
| 1721 } | 1716 } |
| 1722 bpt = bpt->next(); | 1717 bpt = bpt->next(); |
| 1723 } | 1718 } |
| 1724 return NULL; | 1719 return NULL; |
| 1725 } | 1720 } |
| 1726 | 1721 |
| 1727 | 1722 |
| 1723 uword Debugger::GetPatchedStubAddress(uword breakpoint_address) { | |
| 1724 CodeBreakpoint* bpt = GetCodeBreakpoint(breakpoint_address); | |
| 1725 if (bpt != NULL) { | |
| 1726 return bpt->saved_bytes_.target_address_; | |
|
siva
2013/05/23 01:11:26
Is bpt->saved_bytes_.target_address_ a Smi always?
hausner
2013/05/23 18:32:12
Yes, we depend on the fact that target addresses o
| |
| 1727 } | |
| 1728 UNREACHABLE(); | |
| 1729 return NULL; | |
| 1730 } | |
| 1731 | |
| 1732 | |
| 1728 // Remove and delete the source breakpoint bpt and its associated | 1733 // Remove and delete the source breakpoint bpt and its associated |
| 1729 // code breakpoints. | 1734 // code breakpoints. |
| 1730 void Debugger::RemoveBreakpoint(intptr_t bp_id) { | 1735 void Debugger::RemoveBreakpoint(intptr_t bp_id) { |
| 1731 SourceBreakpoint* prev_bpt = NULL; | 1736 SourceBreakpoint* prev_bpt = NULL; |
| 1732 SourceBreakpoint* curr_bpt = src_breakpoints_; | 1737 SourceBreakpoint* curr_bpt = src_breakpoints_; |
| 1733 while (curr_bpt != NULL) { | 1738 while (curr_bpt != NULL) { |
| 1734 if (curr_bpt->id() == bp_id) { | 1739 if (curr_bpt->id() == bp_id) { |
| 1735 if (prev_bpt == NULL) { | 1740 if (prev_bpt == NULL) { |
| 1736 src_breakpoints_ = src_breakpoints_->next(); | 1741 src_breakpoints_ = src_breakpoints_->next(); |
| 1737 } else { | 1742 } else { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1825 } | 1830 } |
| 1826 | 1831 |
| 1827 | 1832 |
| 1828 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 1833 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 1829 ASSERT(bpt->next() == NULL); | 1834 ASSERT(bpt->next() == NULL); |
| 1830 bpt->set_next(code_breakpoints_); | 1835 bpt->set_next(code_breakpoints_); |
| 1831 code_breakpoints_ = bpt; | 1836 code_breakpoints_ = bpt; |
| 1832 } | 1837 } |
| 1833 | 1838 |
| 1834 } // namespace dart | 1839 } // namespace dart |
| OLD | NEW |