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

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

Issue 780173002: Improve debugger in MIPS simulator. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years 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
« no previous file with comments | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 // Only build the simulator if not compiling for real MIPS hardware. 11 // Only build the simulator if not compiling for real MIPS hardware.
12 #if !defined(HOST_ARCH_MIPS) 12 #if !defined(HOST_ARCH_MIPS)
13 13
14 #include "vm/simulator.h" 14 #include "vm/simulator.h"
15 15
16 #include "vm/assembler.h" 16 #include "vm/assembler.h"
17 #include "vm/constants_mips.h" 17 #include "vm/constants_mips.h"
18 #include "vm/disassembler.h" 18 #include "vm/disassembler.h"
19 #include "vm/lockers.h" 19 #include "vm/lockers.h"
20 #include "vm/native_arguments.h" 20 #include "vm/native_arguments.h"
21 #include "vm/stack_frame.h"
21 #include "vm/thread.h" 22 #include "vm/thread.h"
22 23
23 namespace dart { 24 namespace dart {
24 25
25 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution."); 26 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution.");
26 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at."); 27 DEFINE_FLAG(int, stop_sim_at, 0,
28 "Instruction address or instruction count to stop simulator at.");
27 29
28 30
29 // This macro provides a platform independent use of sscanf. The reason for 31 // This macro provides a platform independent use of sscanf. The reason for
30 // SScanF not being implemented in a platform independent way through 32 // SScanF not being implemented in a platform independent way through
31 // OS in the same way as SNPrint is that the Windows C Run-Time 33 // OS in the same way as SNPrint is that the Windows C Run-Time
32 // Library does not provide vsscanf. 34 // Library does not provide vsscanf.
33 #define SScanF sscanf // NOLINT 35 #define SScanF sscanf // NOLINT
34 36
35 37
36 // SimulatorSetjmpBuffer are linked together, and the last created one 38 // SimulatorSetjmpBuffer are linked together, and the last created one
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 void Debug(); 89 void Debug();
88 char* ReadLine(const char* prompt); 90 char* ReadLine(const char* prompt);
89 91
90 private: 92 private:
91 Simulator* sim_; 93 Simulator* sim_;
92 94
93 bool GetValue(char* desc, uint32_t* value); 95 bool GetValue(char* desc, uint32_t* value);
94 bool GetFValue(char* desc, double* value); 96 bool GetFValue(char* desc, double* value);
95 bool GetDValue(char* desc, double* value); 97 bool GetDValue(char* desc, double* value);
96 98
99 static intptr_t GetApproximateTokenIndex(const Code& code, uword pc);
100
101 static void PrintDartFrame(uword pc, uword fp, uword sp,
102 const Function& function,
103 intptr_t token_pos,
104 bool is_optimized,
105 bool is_inlined);
106 void PrintBacktrace();
107
97 static const int32_t kSimulatorBreakpointInstruction = 108 static const int32_t kSimulatorBreakpointInstruction =
98 Instr::kBreakPointInstruction | 109 Instr::kBreakPointInstruction |
99 (Instr::kSimulatorBreakCode << kBreakCodeShift); 110 (Instr::kSimulatorBreakCode << kBreakCodeShift);
100 111
101 // Set or delete a breakpoint. Returns true if successful. 112 // Set or delete a breakpoint. Returns true if successful.
102 bool SetBreakpoint(Instr* breakpc); 113 bool SetBreakpoint(Instr* breakpc);
103 bool DeleteBreakpoint(Instr* breakpc); 114 bool DeleteBreakpoint(Instr* breakpc);
104 115
105 // Undo and redo all breakpoints. This is needed to bracket disassembly and 116 // Undo and redo all breakpoints. This is needed to bracket disassembly and
106 // execution to skip past breakpoints when run from the debugger. 117 // execution to skip past breakpoints when run from the debugger.
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 return false; 207 return false;
197 } 208 }
198 *value = *(reinterpret_cast<uint32_t*>(addr)); 209 *value = *(reinterpret_cast<uint32_t*>(addr));
199 return true; 210 return true;
200 } 211 }
201 } 212 }
202 if (strcmp("pc", desc) == 0) { 213 if (strcmp("pc", desc) == 0) {
203 *value = sim_->get_pc(); 214 *value = sim_->get_pc();
204 return true; 215 return true;
205 } 216 }
217 if (strcmp("icount", desc) == 0) {
218 *value = sim_->get_icount();
219 return true;
220 }
206 bool retval = SScanF(desc, "0x%x", value) == 1; 221 bool retval = SScanF(desc, "0x%x", value) == 1;
207 if (!retval) { 222 if (!retval) {
208 retval = SScanF(desc, "%x", value) == 1; 223 retval = SScanF(desc, "%x", value) == 1;
209 } 224 }
210 return retval; 225 return retval;
211 } 226 }
212 227
213 228
214 bool SimulatorDebugger::GetFValue(char* desc, double* value) { 229 bool SimulatorDebugger::GetFValue(char* desc, double* value) {
215 FRegister freg = LookupFRegisterByName(desc); 230 FRegister freg = LookupFRegisterByName(desc);
(...skipping 28 matching lines...) Expand all
244 return false; 259 return false;
245 } 260 }
246 *value = *(reinterpret_cast<double*>(addr)); 261 *value = *(reinterpret_cast<double*>(addr));
247 return true; 262 return true;
248 } 263 }
249 } 264 }
250 return false; 265 return false;
251 } 266 }
252 267
253 268
269 intptr_t SimulatorDebugger::GetApproximateTokenIndex(const Code& code,
270 uword pc) {
271 intptr_t token_pos = -1;
272 const PcDescriptors& descriptors =
273 PcDescriptors::Handle(code.pc_descriptors());
274 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
275 while (iter.MoveNext()) {
276 if (iter.Pc() == pc) {
277 return iter.TokenPos();
278 } else if ((token_pos <= 0) && (iter.Pc() > pc)) {
279 token_pos = iter.TokenPos();
280 }
281 }
282 return token_pos;
283 }
284
285
286 void SimulatorDebugger::PrintDartFrame(uword pc, uword fp, uword sp,
287 const Function& function,
288 intptr_t token_pos,
289 bool is_optimized,
290 bool is_inlined) {
291 const Script& script = Script::Handle(function.script());
292 const String& func_name = String::Handle(function.QualifiedUserVisibleName());
293 const String& url = String::Handle(script.url());
294 intptr_t line = -1;
295 intptr_t column = -1;
296 if (token_pos >= 0) {
297 script.GetTokenLocation(token_pos, &line, &column);
298 }
299 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd
300 ":%" Pd ")\n",
301 pc, fp, sp,
302 is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
303 func_name.ToCString(),
304 url.ToCString(),
305 line, column);
306 }
307
308
309 void SimulatorDebugger::PrintBacktrace() {
310 StackFrameIterator frames(sim_->get_register(FP),
311 sim_->get_register(SP),
312 sim_->get_pc(),
313 StackFrameIterator::kDontValidateFrames);
314 StackFrame* frame = frames.NextFrame();
315 ASSERT(frame != NULL);
316 Function& function = Function::Handle();
317 Function& inlined_function = Function::Handle();
318 Code& code = Code::Handle();
319 Code& unoptimized_code = Code::Handle();
320 while (frame != NULL) {
321 if (frame->IsDartFrame()) {
322 code = frame->LookupDartCode();
323 function = code.function();
324 if (code.is_optimized()) {
325 // For optimized frames, extract all the inlined functions if any
326 // into the stack trace.
327 InlinedFunctionsIterator it(code, frame->pc());
328 while (!it.Done()) {
329 // Print each inlined frame with its pc in the corresponding
330 // unoptimized frame.
331 inlined_function = it.function();
332 unoptimized_code = it.code();
333 uword unoptimized_pc = it.pc();
334 it.Advance();
335 if (!it.Done()) {
336 PrintDartFrame(unoptimized_pc, frame->fp(), frame->sp(),
337 inlined_function,
338 GetApproximateTokenIndex(unoptimized_code,
339 unoptimized_pc),
340 true, true);
341 }
342 }
343 // Print the optimized inlining frame below.
344 }
345 PrintDartFrame(frame->pc(), frame->fp(), frame->sp(),
346 function,
347 GetApproximateTokenIndex(code, frame->pc()),
348 code.is_optimized(), false);
349 } else {
350 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n",
351 frame->pc(), frame->fp(), frame->sp(),
352 frame->IsEntryFrame() ? "entry" :
353 frame->IsExitFrame() ? "exit" :
354 frame->IsStubFrame() ? "stub" : "invalid");
355 }
356 frame = frames.NextFrame();
357 }
358 }
359
360
254 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { 361 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) {
255 // Check if a breakpoint can be set. If not return without any side-effects. 362 // Check if a breakpoint can be set. If not return without any side-effects.
256 if (sim_->break_pc_ != NULL) { 363 if (sim_->break_pc_ != NULL) {
257 return false; 364 return false;
258 } 365 }
259 366
260 // Set the breakpoint. 367 // Set the breakpoint.
261 sim_->break_pc_ = breakpc; 368 sim_->break_pc_ = breakpc;
262 sim_->break_instr_ = breakpc->InstructionBits(); 369 sim_->break_instr_ = breakpc->InstructionBits();
263 // Not setting the breakpoint instruction in the code itself. It will be set 370 // Not setting the breakpoint instruction in the code itself. It will be set
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 OS::Print("c/cont -- continue execution\n" 445 OS::Print("c/cont -- continue execution\n"
339 "disasm -- disassemble instrs at current pc location\n" 446 "disasm -- disassemble instrs at current pc location\n"
340 " other variants are:\n" 447 " other variants are:\n"
341 " disasm <address>\n" 448 " disasm <address>\n"
342 " disasm <address> <number_of_instructions>\n" 449 " disasm <address> <number_of_instructions>\n"
343 " by default 10 instrs are disassembled\n" 450 " by default 10 instrs are disassembled\n"
344 "del -- delete breakpoints\n" 451 "del -- delete breakpoints\n"
345 "gdb -- transfer control to gdb\n" 452 "gdb -- transfer control to gdb\n"
346 "h/help -- print this help string\n" 453 "h/help -- print this help string\n"
347 "break <address> -- set break point at specified address\n" 454 "break <address> -- set break point at specified address\n"
348 "p/print <reg or value or *addr> -- print integer value\n" 455 "p/print <reg or icount or value or *addr> -- print integer\n"
349 "pf/printfloat <freg or *addr> -- print float value\n" 456 "pf/printfloat <freg or *addr> -- print float value\n"
350 "po/printobject <*reg or *addr> -- print object\n" 457 "po/printobject <*reg or *addr> -- print object\n"
351 "si/stepi -- single step an instruction\n" 458 "si/stepi -- single step an instruction\n"
459 "trace -- toggle execution tracing mode\n"
460 "bt -- print backtrace\n"
352 "unstop -- if current pc is a stop instr make it a nop\n" 461 "unstop -- if current pc is a stop instr make it a nop\n"
353 "q/quit -- Quit the debugger and exit the program\n"); 462 "q/quit -- Quit the debugger and exit the program\n");
354 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { 463 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) {
355 OS::Print("Quitting\n"); 464 OS::Print("Quitting\n");
356 OS::Exit(0); 465 OS::Exit(0);
357 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 466 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
358 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); 467 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
359 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 468 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
360 // Execute the one instruction we broke at with breakpoints disabled. 469 // Execute the one instruction we broke at with breakpoints disabled.
361 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); 470 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 OS::Print("deleting breakpoint failed\n"); 585 OS::Print("deleting breakpoint failed\n");
477 } 586 }
478 } else if (strcmp(cmd, "unstop") == 0) { 587 } else if (strcmp(cmd, "unstop") == 0) {
479 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; 588 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
480 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); 589 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
481 if (stop_instr->IsBreakPoint()) { 590 if (stop_instr->IsBreakPoint()) {
482 stop_instr->SetInstructionBits(Instr::kNopInstruction); 591 stop_instr->SetInstructionBits(Instr::kNopInstruction);
483 } else { 592 } else {
484 OS::Print("Not at debugger stop.\n"); 593 OS::Print("Not at debugger stop.\n");
485 } 594 }
595 } else if (strcmp(cmd, "trace") == 0) {
596 FLAG_trace_sim = !FLAG_trace_sim;
597 OS::Print("execution tracing %s\n", FLAG_trace_sim ? "on" : "off");
598 } else if (strcmp(cmd, "bt") == 0) {
599 PrintBacktrace();
486 } else { 600 } else {
487 OS::Print("Unknown command: %s\n", cmd); 601 OS::Print("Unknown command: %s\n", cmd);
488 } 602 }
489 } 603 }
490 delete[] line; 604 delete[] line;
491 } 605 }
492 606
493 // Add all the breakpoints back to stop execution and enter the debugger 607 // Add all the breakpoints back to stop execution and enter the debugger
494 // shell when hit. 608 // shell when hit.
495 RedoBreakpoints(); 609 RedoBreakpoints();
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 // Same effect on exclusive access state as a successful SC. 1170 // Same effect on exclusive access state as a successful SC.
1057 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); 1171 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address));
1058 } else { 1172 } else {
1059 // Same effect on exclusive access state as an LL. 1173 // Same effect on exclusive access state as an LL.
1060 SetExclusiveAccess(reinterpret_cast<uword>(address)); 1174 SetExclusiveAccess(reinterpret_cast<uword>(address));
1061 } 1175 }
1062 return value; 1176 return value;
1063 } 1177 }
1064 1178
1065 1179
1066 bool Simulator::OverflowFrom(int32_t alu_out,
1067 int32_t left, int32_t right, bool addition) {
1068 bool overflow;
1069 if (addition) {
1070 // Operands have the same sign.
1071 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1072 // And operands and result have different sign.
1073 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1074 } else {
1075 // Operands have different signs.
1076 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1077 // And first operand and result have different signs.
1078 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1079 }
1080 return overflow;
1081 }
1082
1083
1084 // Calls into the Dart runtime are based on this interface. 1180 // Calls into the Dart runtime are based on this interface.
1085 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); 1181 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments);
1086 1182
1087 // Calls to leaf Dart runtime functions are based on this interface. 1183 // Calls to leaf Dart runtime functions are based on this interface.
1088 typedef int32_t (*SimulatorLeafRuntimeCall)( 1184 typedef int32_t (*SimulatorLeafRuntimeCall)(
1089 int32_t r0, int32_t r1, int32_t r2, int32_t r3); 1185 int32_t r0, int32_t r1, int32_t r2, int32_t r3);
1090 1186
1091 // Calls to leaf float Dart runtime functions are based on this interface. 1187 // Calls to leaf float Dart runtime functions are based on this interface.
1092 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); 1188 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1);
1093 1189
(...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after
2165 } 2261 }
2166 pc_ += Instr::kInstrSize; 2262 pc_ += Instr::kInstrSize;
2167 } 2263 }
2168 2264
2169 2265
2170 void Simulator::ExecuteDelaySlot() { 2266 void Simulator::ExecuteDelaySlot() {
2171 ASSERT(pc_ != kEndSimulatingPC); 2267 ASSERT(pc_ != kEndSimulatingPC);
2172 delay_slot_ = true; 2268 delay_slot_ = true;
2173 icount_++; 2269 icount_++;
2174 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); 2270 Instr* instr = Instr::At(pc_ + Instr::kInstrSize);
2175 if ((FLAG_stop_sim_at != 0) && (icount_ == FLAG_stop_sim_at)) { 2271 if (FLAG_stop_sim_at != 0) {
2176 SimulatorDebugger dbg(this); 2272 if (static_cast<int>(icount_) == FLAG_stop_sim_at) {
2177 dbg.Stop(instr, "Instruction count reached"); 2273 SimulatorDebugger dbg(this);
2274 dbg.Stop(instr, "Instruction count reached");
2275 } else if (reinterpret_cast<int>(instr) == FLAG_stop_sim_at) {
2276 SimulatorDebugger dbg(this);
2277 dbg.Stop(instr, "Instruction address reached");
2278 }
2178 } 2279 }
2179 InstructionDecode(instr); 2280 InstructionDecode(instr);
2180 delay_slot_ = false; 2281 delay_slot_ = false;
2181 } 2282 }
2182 2283
2183 2284
2184 void Simulator::Execute() { 2285 void Simulator::Execute() {
2185 if (FLAG_stop_sim_at == 0) { 2286 if (FLAG_stop_sim_at == 0) {
2186 // Fast version of the dispatch loop without checking whether the simulator 2287 // Fast version of the dispatch loop without checking whether the simulator
2187 // should be stopping at a particular executed instruction. 2288 // should be stopping at a particular executed instruction.
2188 while (pc_ != kEndSimulatingPC) { 2289 while (pc_ != kEndSimulatingPC) {
2189 icount_++; 2290 icount_++;
2190 Instr* instr = Instr::At(pc_); 2291 Instr* instr = Instr::At(pc_);
2191 if (IsIllegalAddress(pc_)) { 2292 if (IsIllegalAddress(pc_)) {
2192 HandleIllegalAccess(pc_, instr); 2293 HandleIllegalAccess(pc_, instr);
2193 } else { 2294 } else {
2194 InstructionDecode(instr); 2295 InstructionDecode(instr);
2195 } 2296 }
2196 } 2297 }
2197 } else { 2298 } else {
2198 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 2299 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
2199 // we reach the particular instruction count. 2300 // we reach the particular instruction count or address.
2200 while (pc_ != kEndSimulatingPC) { 2301 while (pc_ != kEndSimulatingPC) {
2201 icount_++; 2302 icount_++;
2202 Instr* instr = Instr::At(pc_); 2303 Instr* instr = Instr::At(pc_);
2203 if (icount_ == FLAG_stop_sim_at) { 2304 if (static_cast<int>(icount_) == FLAG_stop_sim_at) {
2204 SimulatorDebugger dbg(this); 2305 SimulatorDebugger dbg(this);
2205 dbg.Stop(instr, "Instruction count reached"); 2306 dbg.Stop(instr, "Instruction count reached");
2307 } else if (reinterpret_cast<int>(instr) == FLAG_stop_sim_at) {
zra 2014/12/05 17:41:03 Is this useful? Won't the address you want be diff
2308 SimulatorDebugger dbg(this);
2309 dbg.Stop(instr, "Instruction address reached");
2206 } else { 2310 } else {
2207 if (IsIllegalAddress(pc_)) { 2311 if (IsIllegalAddress(pc_)) {
2208 HandleIllegalAccess(pc_, instr); 2312 HandleIllegalAccess(pc_, instr);
2209 } else { 2313 } else {
2210 InstructionDecode(instr); 2314 InstructionDecode(instr);
2211 } 2315 }
2212 } 2316 }
2213 } 2317 }
2214 } 2318 }
2215 } 2319 }
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
2376 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); 2480 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception));
2377 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); 2481 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace));
2378 buf->Longjmp(); 2482 buf->Longjmp();
2379 } 2483 }
2380 2484
2381 } // namespace dart 2485 } // namespace dart
2382 2486
2383 #endif // !defined(HOST_ARCH_MIPS) 2487 #endif // !defined(HOST_ARCH_MIPS)
2384 2488
2385 #endif // defined TARGET_ARCH_MIPS 2489 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698