Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: runtime/vm/debugger.cc

Issue 131853006: Fix debugger stub patching on x64 architecture (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698