| 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 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 | 701 |
| 702 | 702 |
| 703 CodeBreakpoint::CodeBreakpoint(const Function& func, intptr_t pc_desc_index) | 703 CodeBreakpoint::CodeBreakpoint(const Function& func, intptr_t pc_desc_index) |
| 704 : function_(func.raw()), | 704 : function_(func.raw()), |
| 705 pc_desc_index_(pc_desc_index), | 705 pc_desc_index_(pc_desc_index), |
| 706 pc_(0), | 706 pc_(0), |
| 707 line_number_(-1), | 707 line_number_(-1), |
| 708 is_enabled_(false), | 708 is_enabled_(false), |
| 709 src_bpt_(NULL), | 709 src_bpt_(NULL), |
| 710 next_(NULL) { | 710 next_(NULL) { |
| 711 saved_value_ = 0; |
| 711 ASSERT(!func.HasOptimizedCode()); | 712 ASSERT(!func.HasOptimizedCode()); |
| 712 Code& code = Code::Handle(func.unoptimized_code()); | 713 Code& code = Code::Handle(func.unoptimized_code()); |
| 713 ASSERT(!code.IsNull()); // Function must be compiled. | 714 ASSERT(!code.IsNull()); // Function must be compiled. |
| 714 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 715 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 715 ASSERT(pc_desc_index < desc.Length()); | 716 ASSERT(pc_desc_index < desc.Length()); |
| 716 token_pos_ = desc.TokenPos(pc_desc_index); | 717 token_pos_ = desc.TokenPos(pc_desc_index); |
| 717 ASSERT(token_pos_ >= 0); | 718 ASSERT(token_pos_ >= 0); |
| 718 pc_ = desc.PC(pc_desc_index); | 719 pc_ = desc.PC(pc_desc_index); |
| 719 ASSERT(pc_ != 0); | 720 ASSERT(pc_ != 0); |
| 720 breakpoint_kind_ = desc.DescriptorKind(pc_desc_index); | 721 breakpoint_kind_ = desc.DescriptorKind(pc_desc_index); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 751 intptr_t CodeBreakpoint::LineNumber() { | 752 intptr_t CodeBreakpoint::LineNumber() { |
| 752 // Compute line number lazily since it causes scanning of the script. | 753 // Compute line number lazily since it causes scanning of the script. |
| 753 if (line_number_ < 0) { | 754 if (line_number_ < 0) { |
| 754 const Script& script = Script::Handle(SourceCode()); | 755 const Script& script = Script::Handle(SourceCode()); |
| 755 script.GetTokenLocation(token_pos_, &line_number_, NULL); | 756 script.GetTokenLocation(token_pos_, &line_number_, NULL); |
| 756 } | 757 } |
| 757 return line_number_; | 758 return line_number_; |
| 758 } | 759 } |
| 759 | 760 |
| 760 | 761 |
| 761 void CodeBreakpoint::PatchCode() { | |
| 762 ASSERT(!is_enabled_); | |
| 763 switch (breakpoint_kind_) { | |
| 764 case PcDescriptors::kIcCall: { | |
| 765 const Code& code = | |
| 766 Code::Handle(Function::Handle(function_).unoptimized_code()); | |
| 767 saved_bytes_.target_address_ = | |
| 768 CodePatcher::GetInstanceCallAt(pc_, code, NULL); | |
| 769 CodePatcher::PatchInstanceCallAt(pc_, code, | |
| 770 StubCode::BreakpointDynamicEntryPoint()); | |
| 771 break; | |
| 772 } | |
| 773 case PcDescriptors::kUnoptStaticCall: { | |
| 774 const Code& code = | |
| 775 Code::Handle(Function::Handle(function_).unoptimized_code()); | |
| 776 saved_bytes_.target_address_ = | |
| 777 CodePatcher::GetStaticCallTargetAt(pc_, code); | |
| 778 CodePatcher::PatchStaticCallAt(pc_, code, | |
| 779 StubCode::BreakpointStaticEntryPoint()); | |
| 780 break; | |
| 781 } | |
| 782 case PcDescriptors::kRuntimeCall: | |
| 783 case PcDescriptors::kClosureCall: | |
| 784 case PcDescriptors::kReturn: { | |
| 785 const Code& code = | |
| 786 Code::Handle(Function::Handle(function_).unoptimized_code()); | |
| 787 saved_bytes_.target_address_ = | |
| 788 CodePatcher::GetStaticCallTargetAt(pc_, code); | |
| 789 CodePatcher::PatchStaticCallAt(pc_, code, | |
| 790 StubCode::BreakpointRuntimeEntryPoint()); | |
| 791 break; | |
| 792 } | |
| 793 default: | |
| 794 UNREACHABLE(); | |
| 795 } | |
| 796 is_enabled_ = true; | |
| 797 } | |
| 798 | |
| 799 | |
| 800 void CodeBreakpoint::RestoreCode() { | |
| 801 ASSERT(is_enabled_); | |
| 802 switch (breakpoint_kind_) { | |
| 803 case PcDescriptors::kIcCall: { | |
| 804 const Code& code = | |
| 805 Code::Handle(Function::Handle(function_).unoptimized_code()); | |
| 806 CodePatcher::PatchInstanceCallAt(pc_, code, | |
| 807 saved_bytes_.target_address_); | |
| 808 break; | |
| 809 } | |
| 810 case PcDescriptors::kUnoptStaticCall: | |
| 811 case PcDescriptors::kClosureCall: | |
| 812 case PcDescriptors::kRuntimeCall: | |
| 813 case PcDescriptors::kReturn: { | |
| 814 const Code& code = | |
| 815 Code::Handle(Function::Handle(function_).unoptimized_code()); | |
| 816 CodePatcher::PatchStaticCallAt(pc_, code, | |
| 817 saved_bytes_.target_address_); | |
| 818 break; | |
| 819 } | |
| 820 default: | |
| 821 UNREACHABLE(); | |
| 822 } | |
| 823 is_enabled_ = false; | |
| 824 } | |
| 825 | |
| 826 | |
| 827 void CodeBreakpoint::Enable() { | 762 void CodeBreakpoint::Enable() { |
| 828 if (!is_enabled_) { | 763 if (!is_enabled_) { |
| 829 PatchCode(); | 764 PatchCode(); |
| 830 } | 765 } |
| 831 ASSERT(is_enabled_); | 766 ASSERT(is_enabled_); |
| 832 } | 767 } |
| 833 | 768 |
| 834 | 769 |
| 835 void CodeBreakpoint::Disable() { | 770 void CodeBreakpoint::Disable() { |
| 836 if (is_enabled_) { | 771 if (is_enabled_) { |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1022 if (!target_function.HasCode()) { | 957 if (!target_function.HasCode()) { |
| 1023 return; | 958 return; |
| 1024 } | 959 } |
| 1025 } | 960 } |
| 1026 DeoptimizeWorld(); | 961 DeoptimizeWorld(); |
| 1027 ASSERT(!target_function.HasOptimizedCode()); | 962 ASSERT(!target_function.HasOptimizedCode()); |
| 1028 Code& code = Code::Handle(target_function.unoptimized_code()); | 963 Code& code = Code::Handle(target_function.unoptimized_code()); |
| 1029 ASSERT(!code.IsNull()); | 964 ASSERT(!code.IsNull()); |
| 1030 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 965 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 1031 for (intptr_t i = 0; i < desc.Length(); i++) { | 966 for (intptr_t i = 0; i < desc.Length(); i++) { |
| 1032 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); | |
| 1033 if (bpt != NULL) { | |
| 1034 // There is already a breakpoint for this address. Make sure | |
| 1035 // it is enabled. | |
| 1036 bpt->Enable(); | |
| 1037 continue; | |
| 1038 } | |
| 1039 if (IsSafePoint(desc.DescriptorKind(i))) { | 967 if (IsSafePoint(desc.DescriptorKind(i))) { |
| 968 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); |
| 969 if (bpt != NULL) { |
| 970 // There is already a breakpoint for this address. Make sure |
| 971 // it is enabled. |
| 972 bpt->Enable(); |
| 973 continue; |
| 974 } |
| 1040 bpt = new CodeBreakpoint(target_function, i); | 975 bpt = new CodeBreakpoint(target_function, i); |
| 1041 RegisterCodeBreakpoint(bpt); | 976 RegisterCodeBreakpoint(bpt); |
| 1042 bpt->Enable(); | 977 bpt->Enable(); |
| 1043 } | 978 } |
| 1044 } | 979 } |
| 1045 } | 980 } |
| 1046 | 981 |
| 1047 | 982 |
| 1048 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { | 983 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { |
| 1049 if (event_handler_ != NULL) { | 984 if (event_handler_ != NULL) { |
| (...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2168 } | 2103 } |
| 2169 bpt = bpt->next(); | 2104 bpt = bpt->next(); |
| 2170 } | 2105 } |
| 2171 return NULL; | 2106 return NULL; |
| 2172 } | 2107 } |
| 2173 | 2108 |
| 2174 | 2109 |
| 2175 uword Debugger::GetPatchedStubAddress(uword breakpoint_address) { | 2110 uword Debugger::GetPatchedStubAddress(uword breakpoint_address) { |
| 2176 CodeBreakpoint* bpt = GetCodeBreakpoint(breakpoint_address); | 2111 CodeBreakpoint* bpt = GetCodeBreakpoint(breakpoint_address); |
| 2177 if (bpt != NULL) { | 2112 if (bpt != NULL) { |
| 2178 return bpt->saved_bytes_.target_address_; | 2113 return bpt->OrigStubAddress(); |
| 2179 } | 2114 } |
| 2180 UNREACHABLE(); | 2115 UNREACHABLE(); |
| 2181 return 0L; | 2116 return 0L; |
| 2182 } | 2117 } |
| 2183 | 2118 |
| 2184 | 2119 |
| 2185 // Remove and delete the source breakpoint bpt and its associated | 2120 // Remove and delete the source breakpoint bpt and its associated |
| 2186 // code breakpoints. | 2121 // code breakpoints. |
| 2187 void Debugger::RemoveBreakpoint(intptr_t bp_id) { | 2122 void Debugger::RemoveBreakpoint(intptr_t bp_id) { |
| 2188 SourceBreakpoint* prev_bpt = NULL; | 2123 SourceBreakpoint* prev_bpt = NULL; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2281 } | 2216 } |
| 2282 | 2217 |
| 2283 | 2218 |
| 2284 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2219 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 2285 ASSERT(bpt->next() == NULL); | 2220 ASSERT(bpt->next() == NULL); |
| 2286 bpt->set_next(code_breakpoints_); | 2221 bpt->set_next(code_breakpoints_); |
| 2287 code_breakpoints_ = bpt; | 2222 code_breakpoints_ = bpt; |
| 2288 } | 2223 } |
| 2289 | 2224 |
| 2290 } // namespace dart | 2225 } // namespace dart |
| OLD | NEW |