| 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 <math.h> // for isnan. | 5 #include <math.h> // for isnan. |
| 6 #include <setjmp.h> | 6 #include <setjmp.h> |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
| 10 #if defined(TARGET_ARCH_ARM) | 10 #if defined(TARGET_ARCH_ARM) |
| 11 | 11 |
| 12 // Only build the simulator if not compiling for real ARM hardware. | 12 // Only build the simulator if not compiling for real ARM hardware. |
| 13 #if !defined(HOST_ARCH_ARM) | 13 #if !defined(HOST_ARCH_ARM) |
| 14 | 14 |
| 15 #include "vm/simulator.h" | 15 #include "vm/simulator.h" |
| 16 | 16 |
| 17 #include "vm/assembler.h" | 17 #include "vm/assembler.h" |
| 18 #include "vm/constants_arm.h" | 18 #include "vm/constants_arm.h" |
| 19 #include "vm/disassembler.h" | 19 #include "vm/disassembler.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, "Address to stop simulator at."); |
| 27 | 28 |
| 28 | 29 |
| 29 // This macro provides a platform independent use of sscanf. The reason for | 30 // This macro provides a platform independent use of sscanf. The reason for |
| 30 // SScanF not being implemented in a platform independent way through | 31 // SScanF not being implemented in a platform independent way through |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 ((AL << kConditionShift) | (0xf << 24) | kBreakpointSvcCode); | 107 ((AL << kConditionShift) | (0xf << 24) | kBreakpointSvcCode); |
| 107 static const int32_t kNopInstr = // nop | 108 static const int32_t kNopInstr = // nop |
| 108 ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12)); | 109 ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12)); |
| 109 | 110 |
| 110 Simulator* sim_; | 111 Simulator* sim_; |
| 111 | 112 |
| 112 bool GetValue(char* desc, uint32_t* value); | 113 bool GetValue(char* desc, uint32_t* value); |
| 113 bool GetFValue(char* desc, float* value); | 114 bool GetFValue(char* desc, float* value); |
| 114 bool GetDValue(char* desc, double* value); | 115 bool GetDValue(char* desc, double* value); |
| 115 | 116 |
| 117 void PrintDartFrame(uword pc, uword fp, uword sp, |
| 118 const Function& function, |
| 119 intptr_t token_pos, |
| 120 bool is_inlined); |
| 121 void PrintBacktrace(); |
| 122 |
| 116 // Set or delete a breakpoint. Returns true if successful. | 123 // Set or delete a breakpoint. Returns true if successful. |
| 117 bool SetBreakpoint(Instr* breakpc); | 124 bool SetBreakpoint(Instr* breakpc); |
| 118 bool DeleteBreakpoint(Instr* breakpc); | 125 bool DeleteBreakpoint(Instr* breakpc); |
| 119 | 126 |
| 120 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 127 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
| 121 // execution to skip past breakpoints when run from the debugger. | 128 // execution to skip past breakpoints when run from the debugger. |
| 122 void UndoBreakpoints(); | 129 void UndoBreakpoints(); |
| 123 void RedoBreakpoints(); | 130 void RedoBreakpoints(); |
| 124 }; | 131 }; |
| 125 | 132 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 return false; | 254 return false; |
| 248 } | 255 } |
| 249 *value = *(reinterpret_cast<double*>(addr)); | 256 *value = *(reinterpret_cast<double*>(addr)); |
| 250 return true; | 257 return true; |
| 251 } | 258 } |
| 252 } | 259 } |
| 253 return false; | 260 return false; |
| 254 } | 261 } |
| 255 | 262 |
| 256 | 263 |
| 264 void SimulatorDebugger::PrintDartFrame(uword pc, uword fp, uword sp, |
| 265 const Function& function, |
| 266 intptr_t token_pos, |
| 267 bool is_inlined) { |
| 268 const Script& script = Script::Handle(function.script()); |
| 269 const String& func_name = String::Handle(function.QualifiedUserVisibleName()); |
| 270 const String& url = String::Handle(script.url()); |
| 271 intptr_t line = -1; |
| 272 intptr_t column = -1; |
| 273 if (token_pos >= 0) { |
| 274 script.GetTokenLocation(token_pos, &line, &column); |
| 275 } |
| 276 OS::Print("pc=0x%"Px" fp=0x%"Px" sp=0x%"Px" %s%s (%s:%d:%d)\n", |
| 277 pc, fp, sp, |
| 278 is_inlined ? "inlined " : "", |
| 279 func_name.ToCString(), |
| 280 url.ToCString(), |
| 281 line, column); |
| 282 } |
| 283 |
| 284 |
| 285 void SimulatorDebugger::PrintBacktrace() { |
| 286 StackFrameIterator frames(sim_->get_register(FP), |
| 287 sim_->get_register(SP), |
| 288 sim_->get_register(PC), |
| 289 StackFrameIterator::kDontValidateFrames); |
| 290 StackFrame* frame = frames.NextFrame(); |
| 291 ASSERT(frame != NULL); |
| 292 Function& function = Function::Handle(); |
| 293 Code& code = Code::Handle(); |
| 294 while (frame != NULL) { |
| 295 if (frame->IsDartFrame()) { |
| 296 code = frame->LookupDartCode(); |
| 297 if (code.is_optimized()) { |
| 298 // For optimized frames, extract all the inlined functions if any |
| 299 // into the stack trace. |
| 300 for (InlinedFunctionsIterator it(frame); !it.Done(); it.Advance()) { |
| 301 function = it.function(); |
| 302 code = it.code(); |
| 303 uword pc = it.pc(); |
| 304 ASSERT(pc != 0); |
| 305 ASSERT(code.EntryPoint() <= pc); |
| 306 ASSERT(pc < (code.EntryPoint() + code.Size())); |
| 307 PrintDartFrame(pc, frame->fp(), frame->sp(), |
| 308 function, |
| 309 code.GetTokenIndexOfPC(pc), |
| 310 !it.Done()); |
| 311 } |
| 312 } else { |
| 313 function = code.function(); |
| 314 PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), |
| 315 function, |
| 316 code.GetTokenIndexOfPC(frame->pc()), |
| 317 false); |
| 318 } |
| 319 } else { |
| 320 OS::Print("pc=0x%"Px" fp=0x%"Px" sp=0x%"Px" %s frame\n", |
| 321 frame->pc(), frame->fp(), frame->sp(), |
| 322 frame->IsEntryFrame() ? "entry" : |
| 323 frame->IsExitFrame() ? "exit" : |
| 324 frame->IsStubFrame() ? "stub" : "invalid"); |
| 325 } |
| 326 frame = frames.NextFrame(); |
| 327 } |
| 328 } |
| 329 |
| 330 |
| 257 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { | 331 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { |
| 258 // Check if a breakpoint can be set. If not return without any side-effects. | 332 // Check if a breakpoint can be set. If not return without any side-effects. |
| 259 if (sim_->break_pc_ != NULL) { | 333 if (sim_->break_pc_ != NULL) { |
| 260 return false; | 334 return false; |
| 261 } | 335 } |
| 262 | 336 |
| 263 // Set the breakpoint. | 337 // Set the breakpoint. |
| 264 sim_->break_pc_ = breakpc; | 338 sim_->break_pc_ = breakpc; |
| 265 sim_->break_instr_ = breakpc->InstructionBits(); | 339 sim_->break_instr_ = breakpc->InstructionBits(); |
| 266 // Not setting the breakpoint instruction in the code itself. It will be set | 340 // Not setting the breakpoint instruction in the code itself. It will be set |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 "del -- delete breakpoints\n" | 417 "del -- delete breakpoints\n" |
| 344 "flags -- print flag values\n" | 418 "flags -- print flag values\n" |
| 345 "gdb -- transfer control to gdb\n" | 419 "gdb -- transfer control to gdb\n" |
| 346 "h/help -- print this help string\n" | 420 "h/help -- print this help string\n" |
| 347 "break <address> -- set break point at specified address\n" | 421 "break <address> -- set break point at specified address\n" |
| 348 "p/print <reg or value or *addr> -- print integer value\n" | 422 "p/print <reg or value or *addr> -- print integer value\n" |
| 349 "pf/printfloat <sreg or *addr> -- print float value\n" | 423 "pf/printfloat <sreg or *addr> -- print float value\n" |
| 350 "pd/printdouble <dreg or *addr> -- print double value\n" | 424 "pd/printdouble <dreg or *addr> -- print double value\n" |
| 351 "po/printobject <*reg or *addr> -- print object\n" | 425 "po/printobject <*reg or *addr> -- print object\n" |
| 352 "si/stepi -- single step an instruction\n" | 426 "si/stepi -- single step an instruction\n" |
| 427 "trace -- toggle execution tracing mode\n" |
| 428 "bt -- print backtrace\n" |
| 353 "unstop -- if current pc is a stop instr make it a nop\n" | 429 "unstop -- if current pc is a stop instr make it a nop\n" |
| 354 "q/quit -- Quit the debugger and exit the program\n"); | 430 "q/quit -- Quit the debugger and exit the program\n"); |
| 355 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 431 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
| 356 OS::Print("Quitting\n"); | 432 OS::Print("Quitting\n"); |
| 357 OS::Exit(0); | 433 OS::Exit(0); |
| 358 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 434 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
| 359 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 435 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| 360 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 436 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
| 361 // Execute the one instruction we broke at with breakpoints disabled. | 437 // Execute the one instruction we broke at with breakpoints disabled. |
| 362 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 438 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 OS::Print("C flag: %d; ", sim_->fp_c_flag_); | 550 OS::Print("C flag: %d; ", sim_->fp_c_flag_); |
| 475 OS::Print("V flag: %d\n", sim_->fp_v_flag_); | 551 OS::Print("V flag: %d\n", sim_->fp_v_flag_); |
| 476 } else if (strcmp(cmd, "unstop") == 0) { | 552 } else if (strcmp(cmd, "unstop") == 0) { |
| 477 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; | 553 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; |
| 478 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); | 554 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); |
| 479 if (stop_instr->IsSvc() || stop_instr->IsBkpt()) { | 555 if (stop_instr->IsSvc() || stop_instr->IsBkpt()) { |
| 480 stop_instr->SetInstructionBits(kNopInstr); | 556 stop_instr->SetInstructionBits(kNopInstr); |
| 481 } else { | 557 } else { |
| 482 OS::Print("Not at debugger stop.\n"); | 558 OS::Print("Not at debugger stop.\n"); |
| 483 } | 559 } |
| 560 } else if (strcmp(cmd, "trace") == 0) { |
| 561 FLAG_trace_sim = !FLAG_trace_sim; |
| 562 OS::Print("execution tracing %s\n", FLAG_trace_sim ? "on" : "off"); |
| 563 } else if (strcmp(cmd, "bt") == 0) { |
| 564 PrintBacktrace(); |
| 484 } else { | 565 } else { |
| 485 OS::Print("Unknown command: %s\n", cmd); | 566 OS::Print("Unknown command: %s\n", cmd); |
| 486 } | 567 } |
| 487 } | 568 } |
| 488 delete[] line; | 569 delete[] line; |
| 489 } | 570 } |
| 490 | 571 |
| 491 // Add all the breakpoints back to stop execution and enter the debugger | 572 // Add all the breakpoints back to stop execution and enter the debugger |
| 492 // shell when hit. | 573 // shell when hit. |
| 493 RedoBreakpoints(); | 574 RedoBreakpoints(); |
| (...skipping 2428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2922 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 3003 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
| 2923 } | 3004 } |
| 2924 buf->Longjmp(); | 3005 buf->Longjmp(); |
| 2925 } | 3006 } |
| 2926 | 3007 |
| 2927 } // namespace dart | 3008 } // namespace dart |
| 2928 | 3009 |
| 2929 #endif // !defined(HOST_ARCH_ARM) | 3010 #endif // !defined(HOST_ARCH_ARM) |
| 2930 | 3011 |
| 2931 #endif // defined TARGET_ARCH_ARM | 3012 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |