| 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 |