OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 <setjmp.h> | 5 #include <setjmp.h> |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 | 7 |
8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
9 #if defined(TARGET_ARCH_MIPS) | 9 #if defined(TARGET_ARCH_MIPS) |
10 | 10 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 | 98 |
99 static intptr_t GetApproximateTokenIndex(const Code& code, uword pc); | 99 static intptr_t GetApproximateTokenIndex(const Code& code, uword pc); |
100 | 100 |
101 static void PrintDartFrame(uword pc, uword fp, uword sp, | 101 static void PrintDartFrame(uword pc, uword fp, uword sp, |
102 const Function& function, | 102 const Function& function, |
103 intptr_t token_pos, | 103 intptr_t token_pos, |
104 bool is_optimized, | 104 bool is_optimized, |
105 bool is_inlined); | 105 bool is_inlined); |
106 void PrintBacktrace(); | 106 void PrintBacktrace(); |
107 | 107 |
108 static const int32_t kSimulatorBreakpointInstruction = | |
109 Instr::kBreakPointInstruction | | |
110 (Instr::kSimulatorBreakCode << kBreakCodeShift); | |
111 | |
112 // Set or delete a breakpoint. Returns true if successful. | 108 // Set or delete a breakpoint. Returns true if successful. |
113 bool SetBreakpoint(Instr* breakpc); | 109 bool SetBreakpoint(Instr* breakpc); |
114 bool DeleteBreakpoint(Instr* breakpc); | 110 bool DeleteBreakpoint(Instr* breakpc); |
115 | 111 |
116 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 112 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
117 // execution to skip past breakpoints when run from the debugger. | 113 // execution to skip past breakpoints when run from the debugger. |
118 void UndoBreakpoints(); | 114 void UndoBreakpoints(); |
119 void RedoBreakpoints(); | 115 void RedoBreakpoints(); |
120 }; | 116 }; |
121 | 117 |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 | 382 |
387 void SimulatorDebugger::UndoBreakpoints() { | 383 void SimulatorDebugger::UndoBreakpoints() { |
388 if (sim_->break_pc_ != NULL) { | 384 if (sim_->break_pc_ != NULL) { |
389 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); | 385 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
390 } | 386 } |
391 } | 387 } |
392 | 388 |
393 | 389 |
394 void SimulatorDebugger::RedoBreakpoints() { | 390 void SimulatorDebugger::RedoBreakpoints() { |
395 if (sim_->break_pc_ != NULL) { | 391 if (sim_->break_pc_ != NULL) { |
396 sim_->break_pc_->SetInstructionBits(kSimulatorBreakpointInstruction); | 392 sim_->break_pc_->SetInstructionBits(Instr::kSimulatorBreakpointInstruction); |
397 } | 393 } |
398 } | 394 } |
399 | 395 |
400 | 396 |
401 void SimulatorDebugger::Debug() { | 397 void SimulatorDebugger::Debug() { |
402 intptr_t last_pc = -1; | 398 intptr_t last_pc = -1; |
403 bool done = false; | 399 bool done = false; |
404 | 400 |
405 #define COMMAND_SIZE 63 | 401 #define COMMAND_SIZE 63 |
406 #define ARG_SIZE 255 | 402 #define ARG_SIZE 255 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 OS::Print("printobject <*reg or *addr>\n"); | 529 OS::Print("printobject <*reg or *addr>\n"); |
534 } | 530 } |
535 } else if (strcmp(cmd, "disasm") == 0) { | 531 } else if (strcmp(cmd, "disasm") == 0) { |
536 uint32_t start = 0; | 532 uint32_t start = 0; |
537 uint32_t end = 0; | 533 uint32_t end = 0; |
538 if (args == 1) { | 534 if (args == 1) { |
539 start = sim_->get_pc(); | 535 start = sim_->get_pc(); |
540 end = start + (10 * Instr::kInstrSize); | 536 end = start + (10 * Instr::kInstrSize); |
541 } else if (args == 2) { | 537 } else if (args == 2) { |
542 if (GetValue(arg1, &start)) { | 538 if (GetValue(arg1, &start)) { |
543 // no length parameter passed, assume 10 instructions | 539 // No length parameter passed, assume 10 instructions. |
544 if (Simulator::IsIllegalAddress(start)) { | 540 if (Simulator::IsIllegalAddress(start)) { |
545 // If start isn't a valid address, warn and use PC instead | 541 // If start isn't a valid address, warn and use PC instead. |
546 OS::Print("First argument yields invalid address: 0x%x\n", start); | 542 OS::Print("First argument yields invalid address: 0x%x\n", start); |
547 OS::Print("Using PC instead"); | 543 OS::Print("Using PC instead\n"); |
548 start = sim_->get_pc(); | 544 start = sim_->get_pc(); |
549 } | 545 } |
550 end = start + (10 * Instr::kInstrSize); | 546 end = start + (10 * Instr::kInstrSize); |
551 } | 547 } |
552 } else { | 548 } else { |
553 uint32_t length; | 549 uint32_t length; |
554 if (GetValue(arg1, &start) && GetValue(arg2, &length)) { | 550 if (GetValue(arg1, &start) && GetValue(arg2, &length)) { |
555 if (Simulator::IsIllegalAddress(start)) { | 551 if (Simulator::IsIllegalAddress(start)) { |
556 // If start isn't a valid address, warn and use PC instead | 552 // If start isn't a valid address, warn and use PC instead. |
557 OS::Print("First argument yields invalid address: 0x%x\n", start); | 553 OS::Print("First argument yields invalid address: 0x%x\n", start); |
558 OS::Print("Using PC instead\n"); | 554 OS::Print("Using PC instead\n"); |
559 start = sim_->get_pc(); | 555 start = sim_->get_pc(); |
560 } | 556 } |
561 end = start + (length * Instr::kInstrSize); | 557 end = start + (length * Instr::kInstrSize); |
562 } | 558 } |
563 } | 559 } |
564 | 560 if ((start > 0) && (end > start)) { |
565 Disassembler::Disassemble(start, end); | 561 Disassembler::Disassemble(start, end); |
| 562 } else { |
| 563 OS::Print("disasm [<address> [<number_of_instructions>]]\n"); |
| 564 } |
566 } else if (strcmp(cmd, "gdb") == 0) { | 565 } else if (strcmp(cmd, "gdb") == 0) { |
567 OS::Print("relinquishing control to gdb\n"); | 566 OS::Print("relinquishing control to gdb\n"); |
568 OS::DebugBreak(); | 567 OS::DebugBreak(); |
569 OS::Print("regaining control from gdb\n"); | 568 OS::Print("regaining control from gdb\n"); |
570 } else if (strcmp(cmd, "break") == 0) { | 569 } else if (strcmp(cmd, "break") == 0) { |
571 if (args == 2) { | 570 if (args == 2) { |
572 uint32_t addr; | 571 uint32_t addr; |
573 if (GetValue(arg1, &addr)) { | 572 if (GetValue(arg1, &addr)) { |
574 if (!SetBreakpoint(reinterpret_cast<Instr*>(addr))) { | 573 if (!SetBreakpoint(reinterpret_cast<Instr*>(addr))) { |
575 OS::Print("setting breakpoint failed\n"); | 574 OS::Print("setting breakpoint failed\n"); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
774 Redirection* current; | 773 Redirection* current; |
775 for (current = list_; current != NULL; current = current->next_) { | 774 for (current = list_; current != NULL; current = current->next_) { |
776 if (current->address_of_break_instruction() == address_of_break) { | 775 if (current->address_of_break_instruction() == address_of_break) { |
777 return current->external_function_; | 776 return current->external_function_; |
778 } | 777 } |
779 } | 778 } |
780 return 0; | 779 return 0; |
781 } | 780 } |
782 | 781 |
783 private: | 782 private: |
784 static const int32_t kRedirectInstruction = | |
785 Instr::kBreakPointInstruction | (Instr::kRedirectCode << kBreakCodeShift); | |
786 | |
787 Redirection(uword external_function, | 783 Redirection(uword external_function, |
788 Simulator::CallKind call_kind, | 784 Simulator::CallKind call_kind, |
789 int argument_count) | 785 int argument_count) |
790 : external_function_(external_function), | 786 : external_function_(external_function), |
791 call_kind_(call_kind), | 787 call_kind_(call_kind), |
792 argument_count_(argument_count), | 788 argument_count_(argument_count), |
793 break_instruction_(kRedirectInstruction), | 789 break_instruction_(Instr::kSimulatorRedirectInstruction), |
794 next_(list_) { | 790 next_(list_) { |
795 list_ = this; | 791 list_ = this; |
796 } | 792 } |
797 | 793 |
798 uword external_function_; | 794 uword external_function_; |
799 Simulator::CallKind call_kind_; | 795 Simulator::CallKind call_kind_; |
800 int argument_count_; | 796 int argument_count_; |
801 uint32_t break_instruction_; | 797 uint32_t break_instruction_; |
802 Redirection* next_; | 798 Redirection* next_; |
803 static Redirection* list_; | 799 static Redirection* list_; |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1111 | 1107 |
1112 | 1108 |
1113 bool Simulator::HasExclusiveAccessAndOpen(uword addr) { | 1109 bool Simulator::HasExclusiveAccessAndOpen(uword addr) { |
1114 Isolate* isolate = Isolate::Current(); | 1110 Isolate* isolate = Isolate::Current(); |
1115 ASSERT(isolate != NULL); | 1111 ASSERT(isolate != NULL); |
1116 ASSERT(addr != 0); | 1112 ASSERT(addr != 0); |
1117 DEBUG_ASSERT(exclusive_access_lock_->Owner() == isolate); | 1113 DEBUG_ASSERT(exclusive_access_lock_->Owner() == isolate); |
1118 bool result = false; | 1114 bool result = false; |
1119 for (int i = 0; i < kNumAddressTags; i++) { | 1115 for (int i = 0; i < kNumAddressTags; i++) { |
1120 if (exclusive_access_state_[i].isolate == isolate) { | 1116 if (exclusive_access_state_[i].isolate == isolate) { |
1121 // Check whether the current isolates address reservation matches. | 1117 // Check whether the current isolate's address reservation matches. |
1122 if (exclusive_access_state_[i].addr == addr) { | 1118 if (exclusive_access_state_[i].addr == addr) { |
1123 result = true; | 1119 result = true; |
1124 } | 1120 } |
1125 exclusive_access_state_[i].addr = 0; | 1121 exclusive_access_state_[i].addr = 0; |
1126 } else if (exclusive_access_state_[i].addr == addr) { | 1122 } else if (exclusive_access_state_[i].addr == addr) { |
1127 // Other isolates with matching address lose their reservations. | 1123 // Other isolates with matching address lose their reservations. |
1128 exclusive_access_state_[i].addr = 0; | 1124 exclusive_access_state_[i].addr = 0; |
1129 } | 1125 } |
1130 } | 1126 } |
1131 return result; | 1127 return result; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 ASSERT(instr->OpcodeField() == SPECIAL); | 1192 ASSERT(instr->OpcodeField() == SPECIAL); |
1197 ASSERT(instr->FunctionField() == BREAK); | 1193 ASSERT(instr->FunctionField() == BREAK); |
1198 if (instr->BreakCodeField() == Instr::kStopMessageCode) { | 1194 if (instr->BreakCodeField() == Instr::kStopMessageCode) { |
1199 SimulatorDebugger dbg(this); | 1195 SimulatorDebugger dbg(this); |
1200 const char* message = *reinterpret_cast<const char**>( | 1196 const char* message = *reinterpret_cast<const char**>( |
1201 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); | 1197 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); |
1202 set_pc(get_pc() + Instr::kInstrSize); | 1198 set_pc(get_pc() + Instr::kInstrSize); |
1203 dbg.Stop(instr, message); | 1199 dbg.Stop(instr, message); |
1204 // Adjust for extra pc increment. | 1200 // Adjust for extra pc increment. |
1205 set_pc(get_pc() - Instr::kInstrSize); | 1201 set_pc(get_pc() - Instr::kInstrSize); |
1206 } else if (instr->BreakCodeField() == Instr::kMsgMessageCode) { | 1202 } else if (instr->BreakCodeField() == Instr::kSimulatorMessageCode) { |
1207 const char* message = *reinterpret_cast<const char**>( | 1203 const char* message = *reinterpret_cast<const char**>( |
1208 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); | 1204 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); |
1209 if (FLAG_trace_sim) { | 1205 if (FLAG_trace_sim) { |
1210 OS::Print("Message: %s\n", message); | 1206 OS::Print("Message: %s\n", message); |
1211 } else { | 1207 } else { |
1212 OS::PrintErr("Bad break code: 0x%x\n", instr->InstructionBits()); | 1208 OS::PrintErr("Bad break code: 0x%x\n", instr->InstructionBits()); |
1213 UnimplementedInstruction(instr); | 1209 UnimplementedInstruction(instr); |
1214 } | 1210 } |
1215 } else if (instr->BreakCodeField() == Instr::kRedirectCode) { | 1211 } else if (instr->BreakCodeField() == Instr::kSimulatorRedirectCode) { |
1216 SimulatorSetjmpBuffer buffer(this); | 1212 SimulatorSetjmpBuffer buffer(this); |
1217 | 1213 |
1218 if (!setjmp(buffer.buffer_)) { | 1214 if (!setjmp(buffer.buffer_)) { |
1219 int32_t saved_ra = get_register(RA); | 1215 int32_t saved_ra = get_register(RA); |
1220 Redirection* redirection = Redirection::FromBreakInstruction(instr); | 1216 Redirection* redirection = Redirection::FromBreakInstruction(instr); |
1221 uword external = redirection->external_function(); | 1217 uword external = redirection->external_function(); |
1222 if (FLAG_trace_sim) { | 1218 if (FLAG_trace_sim) { |
1223 OS::Print("Call to host function at 0x%" Pd "\n", external); | 1219 OS::Print("Call to host function at 0x%" Pd "\n", external); |
1224 } | 1220 } |
1225 | 1221 |
(...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2292 if (IsIllegalAddress(pc_)) { | 2288 if (IsIllegalAddress(pc_)) { |
2293 HandleIllegalAccess(pc_, instr); | 2289 HandleIllegalAccess(pc_, instr); |
2294 } else { | 2290 } else { |
2295 InstructionDecode(instr); | 2291 InstructionDecode(instr); |
2296 } | 2292 } |
2297 } | 2293 } |
2298 } else { | 2294 } else { |
2299 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 2295 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
2300 // we reach the particular instruction count or address. | 2296 // we reach the particular instruction count or address. |
2301 while (pc_ != kEndSimulatingPC) { | 2297 while (pc_ != kEndSimulatingPC) { |
| 2298 Instr* instr = Instr::At(pc_); |
2302 icount_++; | 2299 icount_++; |
2303 Instr* instr = Instr::At(pc_); | 2300 if (static_cast<intptr_t>(icount_) == FLAG_stop_sim_at) { |
2304 if (static_cast<int>(icount_) == FLAG_stop_sim_at) { | |
2305 SimulatorDebugger dbg(this); | 2301 SimulatorDebugger dbg(this); |
2306 dbg.Stop(instr, "Instruction count reached"); | 2302 dbg.Stop(instr, "Instruction count reached"); |
2307 } else if (reinterpret_cast<int>(instr) == FLAG_stop_sim_at) { | 2303 } else if (reinterpret_cast<intptr_t>(instr) == FLAG_stop_sim_at) { |
2308 SimulatorDebugger dbg(this); | 2304 SimulatorDebugger dbg(this); |
2309 dbg.Stop(instr, "Instruction address reached"); | 2305 dbg.Stop(instr, "Instruction address reached"); |
| 2306 } else if (IsIllegalAddress(pc_)) { |
| 2307 HandleIllegalAccess(pc_, instr); |
2310 } else { | 2308 } else { |
2311 if (IsIllegalAddress(pc_)) { | 2309 InstructionDecode(instr); |
2312 HandleIllegalAccess(pc_, instr); | |
2313 } else { | |
2314 InstructionDecode(instr); | |
2315 } | |
2316 } | 2310 } |
2317 } | 2311 } |
2318 } | 2312 } |
2319 } | 2313 } |
2320 | 2314 |
2321 | 2315 |
2322 int64_t Simulator::Call(int32_t entry, | 2316 int64_t Simulator::Call(int32_t entry, |
2323 int32_t parameter0, | 2317 int32_t parameter0, |
2324 int32_t parameter1, | 2318 int32_t parameter1, |
2325 int32_t parameter2, | 2319 int32_t parameter2, |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2480 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); | 2474 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); |
2481 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 2475 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
2482 buf->Longjmp(); | 2476 buf->Longjmp(); |
2483 } | 2477 } |
2484 | 2478 |
2485 } // namespace dart | 2479 } // namespace dart |
2486 | 2480 |
2487 #endif // !defined(HOST_ARCH_MIPS) | 2481 #endif // !defined(HOST_ARCH_MIPS) |
2488 | 2482 |
2489 #endif // defined TARGET_ARCH_MIPS | 2483 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |