| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64) | 9 #if defined(TARGET_ARCH_ARM64) |
| 10 | 10 |
| 11 // Only build the simulator if not compiling for real ARM hardware. | 11 // Only build the simulator if not compiling for real ARM hardware. |
| 12 #if !defined(HOST_ARCH_ARM64) | 12 #if !defined(HOST_ARCH_ARM64) |
| 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_arm64.h" | 17 #include "vm/constants_arm64.h" |
| 18 #include "vm/cpu.h" | |
| 19 #include "vm/disassembler.h" | 18 #include "vm/disassembler.h" |
| 20 #include "vm/lockers.h" | 19 #include "vm/lockers.h" |
| 21 #include "vm/native_arguments.h" | 20 #include "vm/native_arguments.h" |
| 22 #include "vm/stack_frame.h" | 21 #include "vm/stack_frame.h" |
| 23 #include "vm/thread.h" | 22 #include "vm/thread.h" |
| 24 | 23 |
| 25 namespace dart { | 24 namespace dart { |
| 26 | 25 |
| 27 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution."); | 26 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution."); |
| 28 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."); |
| 29 | 29 |
| 30 | 30 |
| 31 // 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 |
| 32 // SScanF not being implemented in a platform independent way through | 32 // SScanF not being implemented in a platform independent way through |
| 33 // 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 |
| 34 // Library does not provide vsscanf. | 34 // Library does not provide vsscanf. |
| 35 #define SScanF sscanf // NOLINT | 35 #define SScanF sscanf // NOLINT |
| 36 | 36 |
| 37 | 37 |
| 38 // SimulatorSetjmpBuffer are linked together, and the last created one | 38 // SimulatorSetjmpBuffer are linked together, and the last created one |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 explicit SimulatorDebugger(Simulator* sim); | 85 explicit SimulatorDebugger(Simulator* sim); |
| 86 ~SimulatorDebugger(); | 86 ~SimulatorDebugger(); |
| 87 | 87 |
| 88 void Stop(Instr* instr, const char* message); | 88 void Stop(Instr* instr, const char* message); |
| 89 void Debug(); | 89 void Debug(); |
| 90 char* ReadLine(const char* prompt); | 90 char* ReadLine(const char* prompt); |
| 91 | 91 |
| 92 private: | 92 private: |
| 93 Simulator* sim_; | 93 Simulator* sim_; |
| 94 | 94 |
| 95 bool GetValue(char* desc, int64_t* value); | 95 bool GetValue(char* desc, uint64_t* value); |
| 96 bool GetSValue(char* desc, int32_t* value); | 96 bool GetSValue(char* desc, uint32_t* value); |
| 97 bool GetDValue(char* desc, int64_t* value); | 97 bool GetDValue(char* desc, uint64_t* value); |
| 98 bool GetQValue(char* desc, simd_value_t* value); | 98 bool GetQValue(char* desc, simd_value_t* value); |
| 99 // TODO(zra): Breakpoints. | 99 |
| 100 static intptr_t GetApproximateTokenIndex(const Code& code, uword pc); |
| 101 |
| 102 static void PrintDartFrame(uword pc, uword fp, uword sp, |
| 103 const Function& function, |
| 104 intptr_t token_pos, |
| 105 bool is_optimized, |
| 106 bool is_inlined); |
| 107 void PrintBacktrace(); |
| 108 |
| 109 // Set or delete a breakpoint. Returns true if successful. |
| 110 bool SetBreakpoint(Instr* breakpc); |
| 111 bool DeleteBreakpoint(Instr* breakpc); |
| 112 |
| 113 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
| 114 // execution to skip past breakpoints when run from the debugger. |
| 115 void UndoBreakpoints(); |
| 116 void RedoBreakpoints(); |
| 100 }; | 117 }; |
| 101 | 118 |
| 102 | 119 |
| 103 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { | 120 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { |
| 104 sim_ = sim; | 121 sim_ = sim; |
| 105 } | 122 } |
| 106 | 123 |
| 107 | 124 |
| 108 SimulatorDebugger::~SimulatorDebugger() { | 125 SimulatorDebugger::~SimulatorDebugger() { |
| 109 } | 126 } |
| 110 | 127 |
| 128 |
| 111 void SimulatorDebugger::Stop(Instr* instr, const char* message) { | 129 void SimulatorDebugger::Stop(Instr* instr, const char* message) { |
| 112 OS::Print("Simulator hit %s\n", message); | 130 OS::Print("Simulator hit %s\n", message); |
| 113 Debug(); | 131 Debug(); |
| 114 } | 132 } |
| 115 | 133 |
| 116 | 134 |
| 117 static Register LookupCpuRegisterByName(const char* name) { | 135 static Register LookupCpuRegisterByName(const char* name) { |
| 118 static const char* kNames[] = { | 136 static const char* kNames[] = { |
| 119 "r0", "r1", "r2", "r3", | 137 "r0", "r1", "r2", "r3", |
| 120 "r4", "r5", "r6", "r7", | 138 "r4", "r5", "r6", "r7", |
| (...skipping 27 matching lines...) Expand all Loading... |
| 148 static VRegister LookupVRegisterByName(const char* name) { | 166 static VRegister LookupVRegisterByName(const char* name) { |
| 149 int reg_nr = -1; | 167 int reg_nr = -1; |
| 150 bool ok = SScanF(name, "v%d", ®_nr); | 168 bool ok = SScanF(name, "v%d", ®_nr); |
| 151 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfVRegisters)) { | 169 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfVRegisters)) { |
| 152 return static_cast<VRegister>(reg_nr); | 170 return static_cast<VRegister>(reg_nr); |
| 153 } | 171 } |
| 154 return kNoVRegister; | 172 return kNoVRegister; |
| 155 } | 173 } |
| 156 | 174 |
| 157 | 175 |
| 158 bool SimulatorDebugger::GetValue(char* desc, int64_t* value) { | 176 bool SimulatorDebugger::GetValue(char* desc, uint64_t* value) { |
| 159 Register reg = LookupCpuRegisterByName(desc); | 177 Register reg = LookupCpuRegisterByName(desc); |
| 160 if (reg != kNoRegister) { | 178 if (reg != kNoRegister) { |
| 161 if (reg == ZR) { | 179 if (reg == ZR) { |
| 162 *value = 0; | 180 *value = 0; |
| 163 return true; | 181 return true; |
| 164 } | 182 } |
| 165 *value = sim_->get_register(reg); | 183 *value = sim_->get_register(reg); |
| 166 return true; | 184 return true; |
| 167 } | 185 } |
| 168 if (desc[0] == '*') { | 186 if (desc[0] == '*') { |
| 169 int64_t addr; | 187 uint64_t addr; |
| 170 if (GetValue(desc + 1, &addr)) { | 188 if (GetValue(desc + 1, &addr)) { |
| 171 if (Simulator::IsIllegalAddress(addr)) { | 189 if (Simulator::IsIllegalAddress(addr)) { |
| 172 return false; | 190 return false; |
| 173 } | 191 } |
| 174 *value = *(reinterpret_cast<int64_t*>(addr)); | 192 *value = *(reinterpret_cast<int64_t*>(addr)); |
| 175 return true; | 193 return true; |
| 176 } | 194 } |
| 177 } | 195 } |
| 178 if (strcmp("pc", desc) == 0) { | 196 if (strcmp("pc", desc) == 0) { |
| 179 *value = sim_->get_pc(); | 197 *value = sim_->get_pc(); |
| 180 return true; | 198 return true; |
| 181 } | 199 } |
| 200 if (strcmp("icount", desc) == 0) { |
| 201 *value = sim_->get_icount(); |
| 202 return true; |
| 203 } |
| 182 bool retval = SScanF(desc, "0x%"Px64, value) == 1; | 204 bool retval = SScanF(desc, "0x%"Px64, value) == 1; |
| 183 if (!retval) { | 205 if (!retval) { |
| 184 retval = SScanF(desc, "%"Px64, value) == 1; | 206 retval = SScanF(desc, "%"Px64, value) == 1; |
| 185 } | 207 } |
| 186 return retval; | 208 return retval; |
| 187 } | 209 } |
| 188 | 210 |
| 189 | 211 |
| 190 bool SimulatorDebugger::GetSValue(char* desc, int32_t* value) { | 212 bool SimulatorDebugger::GetSValue(char* desc, uint32_t* value) { |
| 191 VRegister vreg = LookupVRegisterByName(desc); | 213 VRegister vreg = LookupVRegisterByName(desc); |
| 192 if (vreg != kNoVRegister) { | 214 if (vreg != kNoVRegister) { |
| 193 *value = sim_->get_vregisters(vreg, 0); | 215 *value = sim_->get_vregisters(vreg, 0); |
| 194 return true; | 216 return true; |
| 195 } | 217 } |
| 196 if (desc[0] == '*') { | 218 if (desc[0] == '*') { |
| 197 int64_t addr; | 219 uint64_t addr; |
| 198 if (GetValue(desc + 1, &addr)) { | 220 if (GetValue(desc + 1, &addr)) { |
| 199 if (Simulator::IsIllegalAddress(addr)) { | 221 if (Simulator::IsIllegalAddress(addr)) { |
| 200 return false; | 222 return false; |
| 201 } | 223 } |
| 202 *value = *(reinterpret_cast<int32_t*>(addr)); | 224 *value = *(reinterpret_cast<uint32_t*>(addr)); |
| 203 return true; | 225 return true; |
| 204 } | 226 } |
| 205 } | 227 } |
| 206 return false; | 228 return false; |
| 207 } | 229 } |
| 208 | 230 |
| 209 | 231 |
| 210 bool SimulatorDebugger::GetDValue(char* desc, int64_t* value) { | 232 bool SimulatorDebugger::GetDValue(char* desc, uint64_t* value) { |
| 211 VRegister vreg = LookupVRegisterByName(desc); | 233 VRegister vreg = LookupVRegisterByName(desc); |
| 212 if (vreg != kNoVRegister) { | 234 if (vreg != kNoVRegister) { |
| 213 *value = sim_->get_vregisterd(vreg, 0); | 235 *value = sim_->get_vregisterd(vreg, 0); |
| 214 return true; | 236 return true; |
| 215 } | 237 } |
| 216 if (desc[0] == '*') { | 238 if (desc[0] == '*') { |
| 217 int64_t addr; | 239 uint64_t addr; |
| 218 if (GetValue(desc + 1, &addr)) { | 240 if (GetValue(desc + 1, &addr)) { |
| 219 if (Simulator::IsIllegalAddress(addr)) { | 241 if (Simulator::IsIllegalAddress(addr)) { |
| 220 return false; | 242 return false; |
| 221 } | 243 } |
| 222 *value = *(reinterpret_cast<int64_t*>(addr)); | 244 *value = *(reinterpret_cast<uint64_t*>(addr)); |
| 223 return true; | 245 return true; |
| 224 } | 246 } |
| 225 } | 247 } |
| 226 return false; | 248 return false; |
| 227 } | 249 } |
| 228 | 250 |
| 229 | 251 |
| 230 bool SimulatorDebugger::GetQValue(char* desc, simd_value_t* value) { | 252 bool SimulatorDebugger::GetQValue(char* desc, simd_value_t* value) { |
| 231 VRegister vreg = LookupVRegisterByName(desc); | 253 VRegister vreg = LookupVRegisterByName(desc); |
| 232 if (vreg != kNoVRegister) { | 254 if (vreg != kNoVRegister) { |
| 233 sim_->get_vregister(vreg, value); | 255 sim_->get_vregister(vreg, value); |
| 234 return true; | 256 return true; |
| 235 } | 257 } |
| 236 if (desc[0] == '*') { | 258 if (desc[0] == '*') { |
| 237 int64_t addr; | 259 uint64_t addr; |
| 238 if (GetValue(desc + 1, &addr)) { | 260 if (GetValue(desc + 1, &addr)) { |
| 239 if (Simulator::IsIllegalAddress(addr)) { | 261 if (Simulator::IsIllegalAddress(addr)) { |
| 240 return false; | 262 return false; |
| 241 } | 263 } |
| 242 *value = *(reinterpret_cast<simd_value_t*>(addr)); | 264 *value = *(reinterpret_cast<simd_value_t*>(addr)); |
| 243 return true; | 265 return true; |
| 244 } | 266 } |
| 245 } | 267 } |
| 246 return false; | 268 return false; |
| 247 } | 269 } |
| 248 | 270 |
| 249 | 271 |
| 272 intptr_t SimulatorDebugger::GetApproximateTokenIndex(const Code& code, |
| 273 uword pc) { |
| 274 intptr_t token_pos = -1; |
| 275 const PcDescriptors& descriptors = |
| 276 PcDescriptors::Handle(code.pc_descriptors()); |
| 277 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); |
| 278 while (iter.MoveNext()) { |
| 279 if (iter.Pc() == pc) { |
| 280 return iter.TokenPos(); |
| 281 } else if ((token_pos <= 0) && (iter.Pc() > pc)) { |
| 282 token_pos = iter.TokenPos(); |
| 283 } |
| 284 } |
| 285 return token_pos; |
| 286 } |
| 287 |
| 288 |
| 289 void SimulatorDebugger::PrintDartFrame(uword pc, uword fp, uword sp, |
| 290 const Function& function, |
| 291 intptr_t token_pos, |
| 292 bool is_optimized, |
| 293 bool is_inlined) { |
| 294 const Script& script = Script::Handle(function.script()); |
| 295 const String& func_name = String::Handle(function.QualifiedUserVisibleName()); |
| 296 const String& url = String::Handle(script.url()); |
| 297 intptr_t line = -1; |
| 298 intptr_t column = -1; |
| 299 if (token_pos >= 0) { |
| 300 script.GetTokenLocation(token_pos, &line, &column); |
| 301 } |
| 302 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd |
| 303 ":%" Pd ")\n", |
| 304 pc, fp, sp, |
| 305 is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", |
| 306 func_name.ToCString(), |
| 307 url.ToCString(), |
| 308 line, column); |
| 309 } |
| 310 |
| 311 |
| 312 void SimulatorDebugger::PrintBacktrace() { |
| 313 StackFrameIterator frames(sim_->get_register(FP), |
| 314 sim_->get_register(SP), |
| 315 sim_->get_pc(), |
| 316 StackFrameIterator::kDontValidateFrames); |
| 317 StackFrame* frame = frames.NextFrame(); |
| 318 ASSERT(frame != NULL); |
| 319 Function& function = Function::Handle(); |
| 320 Function& inlined_function = Function::Handle(); |
| 321 Code& code = Code::Handle(); |
| 322 Code& unoptimized_code = Code::Handle(); |
| 323 while (frame != NULL) { |
| 324 if (frame->IsDartFrame()) { |
| 325 code = frame->LookupDartCode(); |
| 326 function = code.function(); |
| 327 if (code.is_optimized()) { |
| 328 // For optimized frames, extract all the inlined functions if any |
| 329 // into the stack trace. |
| 330 InlinedFunctionsIterator it(code, frame->pc()); |
| 331 while (!it.Done()) { |
| 332 // Print each inlined frame with its pc in the corresponding |
| 333 // unoptimized frame. |
| 334 inlined_function = it.function(); |
| 335 unoptimized_code = it.code(); |
| 336 uword unoptimized_pc = it.pc(); |
| 337 it.Advance(); |
| 338 if (!it.Done()) { |
| 339 PrintDartFrame(unoptimized_pc, frame->fp(), frame->sp(), |
| 340 inlined_function, |
| 341 GetApproximateTokenIndex(unoptimized_code, |
| 342 unoptimized_pc), |
| 343 true, true); |
| 344 } |
| 345 } |
| 346 // Print the optimized inlining frame below. |
| 347 } |
| 348 PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), |
| 349 function, |
| 350 GetApproximateTokenIndex(code, frame->pc()), |
| 351 code.is_optimized(), false); |
| 352 } else { |
| 353 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n", |
| 354 frame->pc(), frame->fp(), frame->sp(), |
| 355 frame->IsEntryFrame() ? "entry" : |
| 356 frame->IsExitFrame() ? "exit" : |
| 357 frame->IsStubFrame() ? "stub" : "invalid"); |
| 358 } |
| 359 frame = frames.NextFrame(); |
| 360 } |
| 361 } |
| 362 |
| 363 |
| 364 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { |
| 365 // Check if a breakpoint can be set. If not return without any side-effects. |
| 366 if (sim_->break_pc_ != NULL) { |
| 367 return false; |
| 368 } |
| 369 |
| 370 // Set the breakpoint. |
| 371 sim_->break_pc_ = breakpc; |
| 372 sim_->break_instr_ = breakpc->InstructionBits(); |
| 373 // Not setting the breakpoint instruction in the code itself. It will be set |
| 374 // when the debugger shell continues. |
| 375 return true; |
| 376 } |
| 377 |
| 378 |
| 379 bool SimulatorDebugger::DeleteBreakpoint(Instr* breakpc) { |
| 380 if (sim_->break_pc_ != NULL) { |
| 381 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
| 382 } |
| 383 |
| 384 sim_->break_pc_ = NULL; |
| 385 sim_->break_instr_ = 0; |
| 386 return true; |
| 387 } |
| 388 |
| 389 |
| 390 void SimulatorDebugger::UndoBreakpoints() { |
| 391 if (sim_->break_pc_ != NULL) { |
| 392 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
| 393 } |
| 394 } |
| 395 |
| 396 |
| 397 void SimulatorDebugger::RedoBreakpoints() { |
| 398 if (sim_->break_pc_ != NULL) { |
| 399 sim_->break_pc_->SetInstructionBits(Instr::kSimulatorBreakpointInstruction); |
| 400 } |
| 401 } |
| 402 |
| 403 |
| 250 void SimulatorDebugger::Debug() { | 404 void SimulatorDebugger::Debug() { |
| 251 intptr_t last_pc = -1; | 405 intptr_t last_pc = -1; |
| 252 bool done = false; | 406 bool done = false; |
| 253 | 407 |
| 254 #define COMMAND_SIZE 63 | 408 #define COMMAND_SIZE 63 |
| 255 #define ARG_SIZE 255 | 409 #define ARG_SIZE 255 |
| 256 | 410 |
| 257 #define STR(a) #a | 411 #define STR(a) #a |
| 258 #define XSTR(a) STR(a) | 412 #define XSTR(a) STR(a) |
| 259 | 413 |
| 260 char cmd[COMMAND_SIZE + 1]; | 414 char cmd[COMMAND_SIZE + 1]; |
| 261 char arg1[ARG_SIZE + 1]; | 415 char arg1[ARG_SIZE + 1]; |
| 262 char arg2[ARG_SIZE + 1]; | 416 char arg2[ARG_SIZE + 1]; |
| 263 | 417 |
| 264 // make sure to have a proper terminating character if reaching the limit | 418 // make sure to have a proper terminating character if reaching the limit |
| 265 cmd[COMMAND_SIZE] = 0; | 419 cmd[COMMAND_SIZE] = 0; |
| 266 arg1[ARG_SIZE] = 0; | 420 arg1[ARG_SIZE] = 0; |
| 267 arg2[ARG_SIZE] = 0; | 421 arg2[ARG_SIZE] = 0; |
| 268 | 422 |
| 269 // TODO(zra): Undo all set breakpoints while running in the debugger shell. | 423 // Undo all set breakpoints while running in the debugger shell. This will |
| 270 // This will make them invisible to all commands. | 424 // make them invisible to all commands. |
| 271 // UndoBreakpoints(); | 425 UndoBreakpoints(); |
| 272 | 426 |
| 273 while (!done) { | 427 while (!done) { |
| 274 if (last_pc != sim_->get_pc()) { | 428 if (last_pc != sim_->get_pc()) { |
| 275 last_pc = sim_->get_pc(); | 429 last_pc = sim_->get_pc(); |
| 276 if (Simulator::IsIllegalAddress(last_pc)) { | 430 if (Simulator::IsIllegalAddress(last_pc)) { |
| 277 OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc); | 431 OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc); |
| 278 } else { | 432 } else { |
| 279 Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize); | 433 Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize); |
| 280 } | 434 } |
| 281 } | 435 } |
| 282 char* line = ReadLine("sim> "); | 436 char* line = ReadLine("sim> "); |
| 283 if (line == NULL) { | 437 if (line == NULL) { |
| 284 FATAL("ReadLine failed"); | 438 FATAL("ReadLine failed"); |
| 285 } else { | 439 } else { |
| 286 // Use sscanf to parse the individual parts of the command line. At the | 440 // Use sscanf to parse the individual parts of the command line. At the |
| 287 // moment no command expects more than two parameters. | 441 // moment no command expects more than two parameters. |
| 288 int args = SScanF(line, | 442 int args = SScanF(line, |
| 289 "%" XSTR(COMMAND_SIZE) "s " | 443 "%" XSTR(COMMAND_SIZE) "s " |
| 290 "%" XSTR(ARG_SIZE) "s " | 444 "%" XSTR(ARG_SIZE) "s " |
| 291 "%" XSTR(ARG_SIZE) "s", | 445 "%" XSTR(ARG_SIZE) "s", |
| 292 cmd, arg1, arg2); | 446 cmd, arg1, arg2); |
| 293 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { | 447 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { |
| 294 OS::Print("c/cont -- continue execution\n" | 448 OS::Print("c/cont -- continue execution\n" |
| 295 "disasm -- disassemble instrs at current pc location\n" | 449 "disasm -- disassemble instrs at current pc location\n" |
| 296 " other variants are:\n" | 450 " other variants are:\n" |
| 297 " disasm <address>\n" | 451 " disasm <address>\n" |
| 298 " disasm <address> <number_of_instructions>\n" | 452 " disasm <address> <number_of_instructions>\n" |
| 299 " by default 10 instrs are disassembled\n" | 453 " by default 10 instrs are disassembled\n" |
| 454 "del -- delete breakpoints\n" |
| 300 "flags -- print flag values\n" | 455 "flags -- print flag values\n" |
| 301 "gdb -- transfer control to gdb\n" | 456 "gdb -- transfer control to gdb\n" |
| 302 "h/help -- print this help string\n" | 457 "h/help -- print this help string\n" |
| 303 "p/print <reg or value or *addr> -- print integer value\n" | 458 "break <address> -- set break point at specified address\n" |
| 459 "p/print <reg or icount or value or *addr> -- print integer\n" |
| 304 "pf/printfloat <vreg or *addr> --print float value\n" | 460 "pf/printfloat <vreg or *addr> --print float value\n" |
| 305 "pd/printdouble <vreg or *addr> -- print double value\n" | 461 "pd/printdouble <vreg or *addr> -- print double value\n" |
| 306 "pq/printquad <vreg or *addr> -- print vector register\n" | 462 "pq/printquad <vreg or *addr> -- print vector register\n" |
| 307 "po/printobject <*reg or *addr> -- print object\n" | 463 "po/printobject <*reg or *addr> -- print object\n" |
| 308 "si/stepi -- single step an instruction\n" | 464 "si/stepi -- single step an instruction\n" |
| 465 "trace -- toggle execution tracing mode\n" |
| 466 "bt -- print backtrace\n" |
| 467 "unstop -- if current pc is a stop instr make it a nop\n" |
| 309 "q/quit -- Quit the debugger and exit the program\n"); | 468 "q/quit -- Quit the debugger and exit the program\n"); |
| 310 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 469 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
| 311 OS::Print("Quitting\n"); | 470 OS::Print("Quitting\n"); |
| 312 OS::Exit(0); | 471 OS::Exit(0); |
| 313 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 472 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
| 314 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 473 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| 315 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 474 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
| 316 // Execute the one instruction we broke at with breakpoints disabled. | 475 // Execute the one instruction we broke at with breakpoints disabled. |
| 317 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 476 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| 318 // Leave the debugger shell. | 477 // Leave the debugger shell. |
| 319 done = true; | 478 done = true; |
| 320 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 479 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
| 321 if (args == 2) { | 480 if (args == 2) { |
| 322 int64_t value; | 481 uint64_t value; |
| 323 if (GetValue(arg1, &value)) { | 482 if (GetValue(arg1, &value)) { |
| 324 OS::Print("%s: %"Pu64" 0x%"Px64"\n", arg1, value, value); | 483 OS::Print("%s: %"Pu64" 0x%"Px64"\n", arg1, value, value); |
| 325 } else { | 484 } else { |
| 326 OS::Print("%s unrecognized\n", arg1); | 485 OS::Print("%s unrecognized\n", arg1); |
| 327 } | 486 } |
| 328 } else { | 487 } else { |
| 329 OS::Print("print <reg or value or *addr>\n"); | 488 OS::Print("print <reg or value or *addr>\n"); |
| 330 } | 489 } |
| 331 } else if ((strcmp(cmd, "pf") == 0) || | 490 } else if ((strcmp(cmd, "pf") == 0) || |
| 332 (strcmp(cmd, "printfloat") == 0)) { | 491 (strcmp(cmd, "printfloat") == 0)) { |
| 333 if (args == 2) { | 492 if (args == 2) { |
| 334 int32_t value; | 493 uint32_t value; |
| 335 if (GetSValue(arg1, &value)) { | 494 if (GetSValue(arg1, &value)) { |
| 336 float svalue = bit_cast<float, int32_t>(value); | 495 float svalue = bit_cast<float, uint32_t>(value); |
| 337 OS::Print("%s: %d 0x%x %.8g\n", | 496 OS::Print("%s: %d 0x%x %.8g\n", |
| 338 arg1, value, value, svalue); | 497 arg1, value, value, svalue); |
| 339 } else { | 498 } else { |
| 340 OS::Print("%s unrecognized\n", arg1); | 499 OS::Print("%s unrecognized\n", arg1); |
| 341 } | 500 } |
| 342 } else { | 501 } else { |
| 343 OS::Print("printfloat <vreg or *addr>\n"); | 502 OS::Print("printfloat <vreg or *addr>\n"); |
| 344 } | 503 } |
| 345 } else if ((strcmp(cmd, "pd") == 0) || | 504 } else if ((strcmp(cmd, "pd") == 0) || |
| 346 (strcmp(cmd, "printdouble") == 0)) { | 505 (strcmp(cmd, "printdouble") == 0)) { |
| 347 if (args == 2) { | 506 if (args == 2) { |
| 348 int64_t long_value; | 507 uint64_t long_value; |
| 349 if (GetDValue(arg1, &long_value)) { | 508 if (GetDValue(arg1, &long_value)) { |
| 350 double dvalue = bit_cast<double, int64_t>(long_value); | 509 double dvalue = bit_cast<double, uint64_t>(long_value); |
| 351 OS::Print("%s: %"Pu64" 0x%"Px64" %.8g\n", | 510 OS::Print("%s: %"Pu64" 0x%"Px64" %.8g\n", |
| 352 arg1, long_value, long_value, dvalue); | 511 arg1, long_value, long_value, dvalue); |
| 353 } else { | 512 } else { |
| 354 OS::Print("%s unrecognized\n", arg1); | 513 OS::Print("%s unrecognized\n", arg1); |
| 355 } | 514 } |
| 356 } else { | 515 } else { |
| 357 OS::Print("printdouble <vreg or *addr>\n"); | 516 OS::Print("printdouble <vreg or *addr>\n"); |
| 358 } | 517 } |
| 359 } else if ((strcmp(cmd, "pq") == 0) || | 518 } else if ((strcmp(cmd, "pq") == 0) || |
| 360 (strcmp(cmd, "printquad") == 0)) { | 519 (strcmp(cmd, "printquad") == 0)) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 381 OS::Print("%s: %d 0x%x %.8g\n", arg1, s3, s3, sval3); | 540 OS::Print("%s: %d 0x%x %.8g\n", arg1, s3, s3, sval3); |
| 382 } else { | 541 } else { |
| 383 OS::Print("%s unrecognized\n", arg1); | 542 OS::Print("%s unrecognized\n", arg1); |
| 384 } | 543 } |
| 385 } else { | 544 } else { |
| 386 OS::Print("printquad <vreg or *addr>\n"); | 545 OS::Print("printquad <vreg or *addr>\n"); |
| 387 } | 546 } |
| 388 } else if ((strcmp(cmd, "po") == 0) || | 547 } else if ((strcmp(cmd, "po") == 0) || |
| 389 (strcmp(cmd, "printobject") == 0)) { | 548 (strcmp(cmd, "printobject") == 0)) { |
| 390 if (args == 2) { | 549 if (args == 2) { |
| 391 int64_t value; | 550 uint64_t value; |
| 392 // Make the dereferencing '*' optional. | 551 // Make the dereferencing '*' optional. |
| 393 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) || | 552 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) || |
| 394 GetValue(arg1, &value)) { | 553 GetValue(arg1, &value)) { |
| 395 if (Isolate::Current()->heap()->Contains(value)) { | 554 if (Isolate::Current()->heap()->Contains(value)) { |
| 396 OS::Print("%s: \n", arg1); | 555 OS::Print("%s: \n", arg1); |
| 397 #if defined(DEBUG) | 556 #if defined(DEBUG) |
| 398 const Object& obj = Object::Handle( | 557 const Object& obj = Object::Handle( |
| 399 reinterpret_cast<RawObject*>(value)); | 558 reinterpret_cast<RawObject*>(value)); |
| 400 obj.Print(); | 559 obj.Print(); |
| 401 #endif // defined(DEBUG) | 560 #endif // defined(DEBUG) |
| 402 } else { | 561 } else { |
| 403 OS::Print("0x%"Px64" is not an object reference\n", value); | 562 OS::Print("0x%"Px64" is not an object reference\n", value); |
| 404 } | 563 } |
| 405 } else { | 564 } else { |
| 406 OS::Print("%s unrecognized\n", arg1); | 565 OS::Print("%s unrecognized\n", arg1); |
| 407 } | 566 } |
| 408 } else { | 567 } else { |
| 409 OS::Print("printobject <*reg or *addr>\n"); | 568 OS::Print("printobject <*reg or *addr>\n"); |
| 410 } | 569 } |
| 411 } else if (strcmp(cmd, "disasm") == 0) { | 570 } else if (strcmp(cmd, "disasm") == 0) { |
| 412 int64_t start = 0; | 571 uint64_t start = 0; |
| 413 int64_t end = 0; | 572 uint64_t end = 0; |
| 414 if (args == 1) { | 573 if (args == 1) { |
| 415 start = sim_->get_pc(); | 574 start = sim_->get_pc(); |
| 416 end = start + (10 * Instr::kInstrSize); | 575 end = start + (10 * Instr::kInstrSize); |
| 417 } else if (args == 2) { | 576 } else if (args == 2) { |
| 418 if (GetValue(arg1, &start)) { | 577 if (GetValue(arg1, &start)) { |
| 419 // no length parameter passed, assume 10 instructions | 578 // No length parameter passed, assume 10 instructions. |
| 420 if (Simulator::IsIllegalAddress(start)) { | 579 if (Simulator::IsIllegalAddress(start)) { |
| 421 // If start isn't a valid address, warn and use PC instead | 580 // If start isn't a valid address, warn and use PC instead. |
| 422 OS::Print("First argument yields invalid address: 0x%"Px64"\n", | 581 OS::Print("First argument yields invalid address: 0x%"Px64"\n", |
| 423 start); | 582 start); |
| 424 OS::Print("Using PC instead"); | 583 OS::Print("Using PC instead\n"); |
| 425 start = sim_->get_pc(); | 584 start = sim_->get_pc(); |
| 426 } | 585 } |
| 427 end = start + (10 * Instr::kInstrSize); | 586 end = start + (10 * Instr::kInstrSize); |
| 428 } | 587 } |
| 429 } else { | 588 } else { |
| 430 int64_t length; | 589 uint64_t length; |
| 431 if (GetValue(arg1, &start) && GetValue(arg2, &length)) { | 590 if (GetValue(arg1, &start) && GetValue(arg2, &length)) { |
| 432 if (Simulator::IsIllegalAddress(start)) { | 591 if (Simulator::IsIllegalAddress(start)) { |
| 433 // If start isn't a valid address, warn and use PC instead | 592 // If start isn't a valid address, warn and use PC instead. |
| 434 OS::Print("First argument yields invalid address: 0x%"Px64"\n", | 593 OS::Print("First argument yields invalid address: 0x%"Px64"\n", |
| 435 start); | 594 start); |
| 436 OS::Print("Using PC instead\n"); | 595 OS::Print("Using PC instead\n"); |
| 437 start = sim_->get_pc(); | 596 start = sim_->get_pc(); |
| 438 } | 597 } |
| 439 end = start + (length * Instr::kInstrSize); | 598 end = start + (length * Instr::kInstrSize); |
| 440 } | 599 } |
| 441 } | 600 } |
| 442 Disassembler::Disassemble(start, end); | 601 if ((start > 0) && (end > start)) { |
| 602 Disassembler::Disassemble(start, end); |
| 603 } else { |
| 604 OS::Print("disasm [<address> [<number_of_instructions>]]\n"); |
| 605 } |
| 606 } else if (strcmp(cmd, "gdb") == 0) { |
| 607 OS::Print("relinquishing control to gdb\n"); |
| 608 OS::DebugBreak(); |
| 609 OS::Print("regaining control from gdb\n"); |
| 610 } else if (strcmp(cmd, "break") == 0) { |
| 611 if (args == 2) { |
| 612 uint64_t addr; |
| 613 if (GetValue(arg1, &addr)) { |
| 614 if (!SetBreakpoint(reinterpret_cast<Instr*>(addr))) { |
| 615 OS::Print("setting breakpoint failed\n"); |
| 616 } |
| 617 } else { |
| 618 OS::Print("%s unrecognized\n", arg1); |
| 619 } |
| 620 } else { |
| 621 OS::Print("break <addr>\n"); |
| 622 } |
| 623 } else if (strcmp(cmd, "del") == 0) { |
| 624 if (!DeleteBreakpoint(NULL)) { |
| 625 OS::Print("deleting breakpoint failed\n"); |
| 626 } |
| 443 } else if (strcmp(cmd, "flags") == 0) { | 627 } else if (strcmp(cmd, "flags") == 0) { |
| 444 OS::Print("APSR: "); | 628 OS::Print("APSR: "); |
| 445 OS::Print("N flag: %d; ", sim_->n_flag_); | 629 OS::Print("N flag: %d; ", sim_->n_flag_); |
| 446 OS::Print("Z flag: %d; ", sim_->z_flag_); | 630 OS::Print("Z flag: %d; ", sim_->z_flag_); |
| 447 OS::Print("C flag: %d; ", sim_->c_flag_); | 631 OS::Print("C flag: %d; ", sim_->c_flag_); |
| 448 OS::Print("V flag: %d\n", sim_->v_flag_); | 632 OS::Print("V flag: %d\n", sim_->v_flag_); |
| 449 } else if (strcmp(cmd, "gdb") == 0) { | 633 } else if (strcmp(cmd, "unstop") == 0) { |
| 450 OS::Print("relinquishing control to gdb\n"); | 634 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; |
| 451 OS::DebugBreak(); | 635 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); |
| 452 OS::Print("regaining control from gdb\n"); | 636 if (stop_instr->IsExceptionGenOp()) { |
| 637 stop_instr->SetInstructionBits(Instr::kNopInstruction); |
| 638 } else { |
| 639 OS::Print("Not at debugger stop.\n"); |
| 640 } |
| 641 } else if (strcmp(cmd, "trace") == 0) { |
| 642 FLAG_trace_sim = !FLAG_trace_sim; |
| 643 OS::Print("execution tracing %s\n", FLAG_trace_sim ? "on" : "off"); |
| 644 } else if (strcmp(cmd, "bt") == 0) { |
| 645 PrintBacktrace(); |
| 453 } else { | 646 } else { |
| 454 OS::Print("Unknown command: %s\n", cmd); | 647 OS::Print("Unknown command: %s\n", cmd); |
| 455 } | 648 } |
| 456 } | 649 } |
| 457 delete[] line; | 650 delete[] line; |
| 458 } | 651 } |
| 459 | 652 |
| 460 // TODO(zra): Add all the breakpoints back to stop execution and enter the | 653 // Add all the breakpoints back to stop execution and enter the debugger |
| 461 // debugger shell when hit. | 654 // shell when hit. |
| 462 // RedoBreakpoints(); | 655 RedoBreakpoints(); |
| 463 | 656 |
| 464 #undef COMMAND_SIZE | 657 #undef COMMAND_SIZE |
| 465 #undef ARG_SIZE | 658 #undef ARG_SIZE |
| 466 | 659 |
| 467 #undef STR | 660 #undef STR |
| 468 #undef XSTR | 661 #undef XSTR |
| 469 } | 662 } |
| 470 | 663 |
| 471 | 664 |
| 472 char* SimulatorDebugger::ReadLine(const char* prompt) { | 665 char* SimulatorDebugger::ReadLine(const char* prompt) { |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 | 992 |
| 800 | 993 |
| 801 int64_t Simulator::get_last_pc() const { | 994 int64_t Simulator::get_last_pc() const { |
| 802 return last_pc_; | 995 return last_pc_; |
| 803 } | 996 } |
| 804 | 997 |
| 805 | 998 |
| 806 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { | 999 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { |
| 807 uword fault_pc = get_pc(); | 1000 uword fault_pc = get_pc(); |
| 808 uword last_pc = get_last_pc(); | 1001 uword last_pc = get_last_pc(); |
| 809 // TODO(zra): drop into debugger. | |
| 810 char buffer[128]; | 1002 char buffer[128]; |
| 811 snprintf(buffer, sizeof(buffer), | 1003 snprintf(buffer, sizeof(buffer), |
| 812 "illegal memory access at 0x%" Px ", pc=0x%" Px ", last_pc=0x%" Px"\n", | 1004 "illegal memory access at 0x%" Px ", pc=0x%" Px ", last_pc=0x%" Px"\n", |
| 813 addr, fault_pc, last_pc); | 1005 addr, fault_pc, last_pc); |
| 814 SimulatorDebugger dbg(this); | 1006 SimulatorDebugger dbg(this); |
| 815 dbg.Stop(instr, buffer); | 1007 dbg.Stop(instr, buffer); |
| 816 // The debugger will return control in non-interactive mode. | 1008 // The debugger will return control in non-interactive mode. |
| 817 FATAL("Cannot continue execution after illegal memory access."); | 1009 FATAL("Cannot continue execution after illegal memory access."); |
| 818 } | 1010 } |
| 819 | 1011 |
| (...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1471 | 1663 |
| 1472 | 1664 |
| 1473 void Simulator::DecodeExceptionGen(Instr* instr) { | 1665 void Simulator::DecodeExceptionGen(Instr* instr) { |
| 1474 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && | 1666 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && |
| 1475 (instr->Bits(21, 3) == 0)) { | 1667 (instr->Bits(21, 3) == 0)) { |
| 1476 // Format(instr, "svc 'imm16"); | 1668 // Format(instr, "svc 'imm16"); |
| 1477 UnimplementedInstruction(instr); | 1669 UnimplementedInstruction(instr); |
| 1478 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && | 1670 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && |
| 1479 (instr->Bits(21, 3) == 1)) { | 1671 (instr->Bits(21, 3) == 1)) { |
| 1480 // Format(instr, "brk 'imm16"); | 1672 // Format(instr, "brk 'imm16"); |
| 1481 UnimplementedInstruction(instr); | 1673 SimulatorDebugger dbg(this); |
| 1674 uint16_t imm = static_cast<uint16_t>(instr->Imm16Field()); |
| 1675 char buffer[32]; |
| 1676 snprintf(buffer, sizeof(buffer), "brk #0x%x", imm); |
| 1677 set_pc(get_pc() + Instr::kInstrSize); |
| 1678 dbg.Stop(instr, buffer); |
| 1482 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && | 1679 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && |
| 1483 (instr->Bits(21, 3) == 2)) { | 1680 (instr->Bits(21, 3) == 2)) { |
| 1484 // Format(instr, "hlt 'imm16"); | 1681 // Format(instr, "hlt 'imm16"); |
| 1485 uint16_t imm = static_cast<uint16_t>(instr->Imm16Field()); | 1682 uint16_t imm = static_cast<uint16_t>(instr->Imm16Field()); |
| 1486 if (imm == kImmExceptionIsDebug) { | 1683 if (imm == Instr::kSimulatorMessageCode) { |
| 1487 SimulatorDebugger dbg(this); | 1684 SimulatorDebugger dbg(this); |
| 1488 const char* message = *reinterpret_cast<const char**>( | 1685 const char* message = *reinterpret_cast<const char**>( |
| 1489 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); | 1686 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); |
| 1490 set_pc(get_pc() + Instr::kInstrSize); | 1687 set_pc(get_pc() + Instr::kInstrSize); |
| 1491 dbg.Stop(instr, message); | 1688 dbg.Stop(instr, message); |
| 1492 } else if (imm == kImmExceptionIsPrintf) { | 1689 } else if (imm == Instr::kSimulatorBreakCode) { |
| 1493 const char* message = *reinterpret_cast<const char**>( | 1690 SimulatorDebugger dbg(this); |
| 1494 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); | 1691 dbg.Stop(instr, "breakpoint"); |
| 1495 OS::Print("Simulator hit: %s", message); | 1692 } else if (imm == Instr::kSimulatorRedirectCode) { |
| 1496 } else if (imm == kImmExceptionIsRedirectedCall) { | |
| 1497 DoRedirectedCall(instr); | 1693 DoRedirectedCall(instr); |
| 1498 } else { | 1694 } else { |
| 1499 UnimplementedInstruction(instr); | 1695 UnimplementedInstruction(instr); |
| 1500 } | 1696 } |
| 1697 } else { |
| 1698 UnimplementedInstruction(instr); |
| 1501 } | 1699 } |
| 1502 } | 1700 } |
| 1503 | 1701 |
| 1504 | 1702 |
| 1505 void Simulator::DecodeSystem(Instr* instr) { | 1703 void Simulator::DecodeSystem(Instr* instr) { |
| 1506 if ((instr->Bits(0, 8) == 0x1f) && (instr->Bits(12, 4) == 2) && | 1704 if ((instr->Bits(0, 8) == 0x1f) && (instr->Bits(12, 4) == 2) && |
| 1507 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) && | 1705 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) && |
| 1508 (instr->Bit(21) == 0)) { | 1706 (instr->Bit(21) == 0)) { |
| 1509 if (instr->Bits(8, 4) == 0) { | 1707 if (instr->Bits(8, 4) == 0) { |
| 1510 // Format(instr, "nop"); | 1708 // Format(instr, "nop"); |
| (...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3115 icount_++; | 3313 icount_++; |
| 3116 if (IsIllegalAddress(program_counter)) { | 3314 if (IsIllegalAddress(program_counter)) { |
| 3117 HandleIllegalAccess(program_counter, instr); | 3315 HandleIllegalAccess(program_counter, instr); |
| 3118 } else { | 3316 } else { |
| 3119 InstructionDecode(instr); | 3317 InstructionDecode(instr); |
| 3120 } | 3318 } |
| 3121 program_counter = get_pc(); | 3319 program_counter = get_pc(); |
| 3122 } | 3320 } |
| 3123 } else { | 3321 } else { |
| 3124 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 3322 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
| 3125 // we reach the particular instruction count. | 3323 // we reach the particular instruction count or address. |
| 3126 while (program_counter != kEndSimulatingPC) { | 3324 while (program_counter != kEndSimulatingPC) { |
| 3127 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 3325 Instr* instr = reinterpret_cast<Instr*>(program_counter); |
| 3128 icount_++; | 3326 icount_++; |
| 3129 if (icount_ == FLAG_stop_sim_at) { | 3327 if (static_cast<intptr_t>(icount_) == FLAG_stop_sim_at) { |
| 3130 // TODO(zra): Add a debugger. | 3328 SimulatorDebugger dbg(this); |
| 3131 UNIMPLEMENTED(); | 3329 dbg.Stop(instr, "Instruction count reached"); |
| 3330 } else if (reinterpret_cast<intptr_t>(instr) == FLAG_stop_sim_at) { |
| 3331 SimulatorDebugger dbg(this); |
| 3332 dbg.Stop(instr, "Instruction address reached"); |
| 3132 } else if (IsIllegalAddress(program_counter)) { | 3333 } else if (IsIllegalAddress(program_counter)) { |
| 3133 HandleIllegalAccess(program_counter, instr); | 3334 HandleIllegalAccess(program_counter, instr); |
| 3134 } else { | 3335 } else { |
| 3135 InstructionDecode(instr); | 3336 InstructionDecode(instr); |
| 3136 } | 3337 } |
| 3137 program_counter = get_pc(); | 3338 program_counter = get_pc(); |
| 3138 } | 3339 } |
| 3139 } | 3340 } |
| 3140 } | 3341 } |
| 3141 | 3342 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3269 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); | 3470 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); |
| 3270 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); | 3471 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); |
| 3271 buf->Longjmp(); | 3472 buf->Longjmp(); |
| 3272 } | 3473 } |
| 3273 | 3474 |
| 3274 } // namespace dart | 3475 } // namespace dart |
| 3275 | 3476 |
| 3276 #endif // !defined(HOST_ARCH_ARM64) | 3477 #endif // !defined(HOST_ARCH_ARM64) |
| 3277 | 3478 |
| 3278 #endif // defined TARGET_ARCH_ARM64 | 3479 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |