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 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1004 function.SwitchToUnoptimizedCode(); | 939 function.SwitchToUnoptimizedCode(); |
1005 } | 940 } |
1006 } | 941 } |
1007 } | 942 } |
1008 } | 943 } |
1009 } | 944 } |
1010 } | 945 } |
1011 | 946 |
1012 | 947 |
1013 void Debugger::InstrumentForStepping(const Function& target_function) { | 948 void Debugger::InstrumentForStepping(const Function& target_function) { |
| 949 //printf("Instrumenting: %s\n", target_function.ToFullyQualifiedCString()); |
1014 if (target_function.is_native()) { | 950 if (target_function.is_native()) { |
1015 // Can't instrument native functions. | 951 // Can't instrument native functions. |
1016 return; | 952 return; |
1017 } | 953 } |
1018 if (!target_function.HasCode()) { | 954 if (!target_function.HasCode()) { |
1019 Compiler::CompileFunction(target_function); | 955 Compiler::CompileFunction(target_function); |
1020 // If there were any errors, ignore them silently and return without | 956 // If there were any errors, ignore them silently and return without |
1021 // adding breakpoints to target. | 957 // adding breakpoints to target. |
1022 if (!target_function.HasCode()) { | 958 if (!target_function.HasCode()) { |
1023 return; | 959 return; |
1024 } | 960 } |
1025 } | 961 } |
1026 DeoptimizeWorld(); | 962 DeoptimizeWorld(); |
1027 ASSERT(!target_function.HasOptimizedCode()); | 963 ASSERT(!target_function.HasOptimizedCode()); |
1028 Code& code = Code::Handle(target_function.unoptimized_code()); | 964 Code& code = Code::Handle(target_function.unoptimized_code()); |
1029 ASSERT(!code.IsNull()); | 965 ASSERT(!code.IsNull()); |
1030 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 966 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
1031 for (intptr_t i = 0; i < desc.Length(); i++) { | 967 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))) { | 968 if (IsSafePoint(desc.DescriptorKind(i))) { |
| 969 CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(i)); |
| 970 if (bpt != NULL) { |
| 971 // There is already a breakpoint for this address. Make sure |
| 972 // it is enabled. |
| 973 //printf("IFS: found bp i %ld pc 0x%lx\n", i, desc.PC(i)); |
| 974 bpt->Enable(); |
| 975 continue; |
| 976 } |
| 977 //printf("IFS: make new bp i %ld pc 0x%lx\n", i, desc.PC(i)); |
1040 bpt = new CodeBreakpoint(target_function, i); | 978 bpt = new CodeBreakpoint(target_function, i); |
1041 RegisterCodeBreakpoint(bpt); | 979 RegisterCodeBreakpoint(bpt); |
1042 bpt->Enable(); | 980 bpt->Enable(); |
1043 } | 981 } |
1044 } | 982 } |
1045 } | 983 } |
1046 | 984 |
1047 | 985 |
1048 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { | 986 void Debugger::SignalBpResolved(SourceBreakpoint* bpt) { |
1049 if (event_handler_ != NULL) { | 987 if (event_handler_ != NULL) { |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 } | 1290 } |
1353 | 1291 |
1354 | 1292 |
1355 void Debugger::MakeCodeBreakpointsAt(const Function& func, | 1293 void Debugger::MakeCodeBreakpointsAt(const Function& func, |
1356 SourceBreakpoint* bpt) { | 1294 SourceBreakpoint* bpt) { |
1357 ASSERT((bpt != NULL) && bpt->IsResolved()); | 1295 ASSERT((bpt != NULL) && bpt->IsResolved()); |
1358 ASSERT(!func.HasOptimizedCode()); | 1296 ASSERT(!func.HasOptimizedCode()); |
1359 Code& code = Code::Handle(func.unoptimized_code()); | 1297 Code& code = Code::Handle(func.unoptimized_code()); |
1360 ASSERT(!code.IsNull()); | 1298 ASSERT(!code.IsNull()); |
1361 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | 1299 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); |
| 1300 //printf("XXX make code bp at %ld\n", bpt->token_pos_); |
1362 for (intptr_t i = 0; i < desc.Length(); i++) { | 1301 for (intptr_t i = 0; i < desc.Length(); i++) { |
1363 intptr_t desc_token_pos = desc.TokenPos(i); | 1302 intptr_t desc_token_pos = desc.TokenPos(i); |
1364 if ((desc_token_pos == bpt->token_pos_) && | 1303 if ((desc_token_pos == bpt->token_pos_) && |
1365 IsSafePoint(desc.DescriptorKind(i))) { | 1304 IsSafePoint(desc.DescriptorKind(i))) { |
| 1305 //printf("XXX found matching safe point i %ld pos %ld\n", i, desc_token_pos); |
1366 CodeBreakpoint* code_bpt = GetCodeBreakpoint(desc.PC(i)); | 1306 CodeBreakpoint* code_bpt = GetCodeBreakpoint(desc.PC(i)); |
1367 if (code_bpt == NULL) { | 1307 if (code_bpt == NULL) { |
| 1308 //printf("making new code breakpoint\n"); |
1368 // No code breakpoint for this code exists; create one. | 1309 // No code breakpoint for this code exists; create one. |
1369 code_bpt = new CodeBreakpoint(func, i); | 1310 code_bpt = new CodeBreakpoint(func, i); |
1370 RegisterCodeBreakpoint(code_bpt); | 1311 RegisterCodeBreakpoint(code_bpt); |
1371 } | 1312 } |
1372 code_bpt->set_src_bpt(bpt); | 1313 //else printf("found existing code breakpoint pc 0x%lx srcbp 0x%p\n", code_bpt->
pc(), code_bpt->src_bpt()); |
| 1314 // code_bpt->set_src_bpt(bpt); |
1373 if (bpt->IsEnabled()) { | 1315 if (bpt->IsEnabled()) { |
1374 code_bpt->Enable(); | 1316 code_bpt->Enable(); |
1375 } | 1317 } |
1376 } | 1318 } |
1377 } | 1319 } |
1378 } | 1320 } |
1379 | 1321 |
1380 | 1322 |
1381 void Debugger::FindEquivalentFunctions(const Script& script, | 1323 void Debugger::FindEquivalentFunctions(const Script& script, |
1382 intptr_t start_pos, | 1324 intptr_t start_pos, |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 func.token_pos(), | 1496 func.token_pos(), |
1555 func.end_token_pos(), | 1497 func.end_token_pos(), |
1556 &functions); | 1498 &functions); |
1557 const intptr_t num_functions = functions.Length(); | 1499 const intptr_t num_functions = functions.Length(); |
1558 // We must have found at least one function: func. | 1500 // We must have found at least one function: func. |
1559 ASSERT(num_functions > 0); | 1501 ASSERT(num_functions > 0); |
1560 // Create code breakpoints for all compiled functions we found. | 1502 // Create code breakpoints for all compiled functions we found. |
1561 for (intptr_t i = 0; i < num_functions; i++) { | 1503 for (intptr_t i = 0; i < num_functions; i++) { |
1562 func ^= functions.At(i); | 1504 func ^= functions.At(i); |
1563 if (func.HasCode()) { | 1505 if (func.HasCode()) { |
| 1506 //printf("func %s\n", func.ToFullyQualifiedCString()); |
1564 MakeCodeBreakpointsAt(func, bpt); | 1507 MakeCodeBreakpointsAt(func, bpt); |
1565 } | 1508 } |
1566 } | 1509 } |
1567 bpt->Enable(); | 1510 bpt->Enable(); |
1568 SignalBpResolved(bpt); | 1511 SignalBpResolved(bpt); |
1569 return bpt; | 1512 return bpt; |
1570 } | 1513 } |
1571 } | 1514 } |
1572 // There is no compiled function at this token position. | 1515 // There is no compiled function at this token position. |
1573 // Register an unresolved breakpoint. | 1516 // Register an unresolved breakpoint. |
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2172 if (bpt->pc() == breakpoint_address) { | 2115 if (bpt->pc() == breakpoint_address) { |
2173 return bpt; | 2116 return bpt; |
2174 } | 2117 } |
2175 bpt = bpt->next(); | 2118 bpt = bpt->next(); |
2176 } | 2119 } |
2177 return NULL; | 2120 return NULL; |
2178 } | 2121 } |
2179 | 2122 |
2180 | 2123 |
2181 uword Debugger::GetPatchedStubAddress(uword breakpoint_address) { | 2124 uword Debugger::GetPatchedStubAddress(uword breakpoint_address) { |
| 2125 //printf("GPSA 0x%lx\n", breakpoint_address); |
2182 CodeBreakpoint* bpt = GetCodeBreakpoint(breakpoint_address); | 2126 CodeBreakpoint* bpt = GetCodeBreakpoint(breakpoint_address); |
2183 if (bpt != NULL) { | 2127 if (bpt != NULL) { |
2184 return bpt->saved_bytes_.target_address_; | 2128 return bpt->OrigStubAddress(); |
2185 } | 2129 } |
2186 UNREACHABLE(); | 2130 UNREACHABLE(); |
2187 return 0L; | 2131 return 0L; |
2188 } | 2132 } |
2189 | 2133 |
2190 | 2134 |
2191 // Remove and delete the source breakpoint bpt and its associated | 2135 // Remove and delete the source breakpoint bpt and its associated |
2192 // code breakpoints. | 2136 // code breakpoints. |
2193 void Debugger::RemoveBreakpoint(intptr_t bp_id) { | 2137 void Debugger::RemoveBreakpoint(intptr_t bp_id) { |
2194 SourceBreakpoint* prev_bpt = NULL; | 2138 SourceBreakpoint* prev_bpt = NULL; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2231 } | 2175 } |
2232 | 2176 |
2233 | 2177 |
2234 // Remove and delete internal breakpoints, i.e. breakpoints that | 2178 // Remove and delete internal breakpoints, i.e. breakpoints that |
2235 // are not associated with a source breakpoint. | 2179 // are not associated with a source breakpoint. |
2236 void Debugger::RemoveInternalBreakpoints() { | 2180 void Debugger::RemoveInternalBreakpoints() { |
2237 CodeBreakpoint* prev_bpt = NULL; | 2181 CodeBreakpoint* prev_bpt = NULL; |
2238 CodeBreakpoint* curr_bpt = code_breakpoints_; | 2182 CodeBreakpoint* curr_bpt = code_breakpoints_; |
2239 while (curr_bpt != NULL) { | 2183 while (curr_bpt != NULL) { |
2240 if (curr_bpt->src_bpt() == NULL) { | 2184 if (curr_bpt->src_bpt() == NULL) { |
| 2185 //printf("RIBP for 0x%lx\n", curr_bpt->pc()); |
2241 if (prev_bpt == NULL) { | 2186 if (prev_bpt == NULL) { |
2242 code_breakpoints_ = code_breakpoints_->next(); | 2187 code_breakpoints_ = code_breakpoints_->next(); |
2243 } else { | 2188 } else { |
2244 prev_bpt->set_next(curr_bpt->next()); | 2189 prev_bpt->set_next(curr_bpt->next()); |
2245 } | 2190 } |
2246 CodeBreakpoint* temp_bpt = curr_bpt; | 2191 CodeBreakpoint* temp_bpt = curr_bpt; |
2247 curr_bpt = curr_bpt->next(); | 2192 curr_bpt = curr_bpt->next(); |
2248 temp_bpt->Disable(); | 2193 temp_bpt->Disable(); |
2249 delete temp_bpt; | 2194 delete temp_bpt; |
2250 } else { | 2195 } else { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2287 } | 2232 } |
2288 | 2233 |
2289 | 2234 |
2290 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 2235 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
2291 ASSERT(bpt->next() == NULL); | 2236 ASSERT(bpt->next() == NULL); |
2292 bpt->set_next(code_breakpoints_); | 2237 bpt->set_next(code_breakpoints_); |
2293 code_breakpoints_ = bpt; | 2238 code_breakpoints_ = bpt; |
2294 } | 2239 } |
2295 | 2240 |
2296 } // namespace dart | 2241 } // namespace dart |
OLD | NEW |