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

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

Issue 789903002: Complete and clean up breakpoint support in all 3 debuggers embedded in MIPS, (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_arm64.h ('k') | runtime/vm/simulator_mips.cc » ('j') | 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) 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
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
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", &reg_nr); 168 bool ok = SScanF(name, "v%d", &reg_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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | runtime/vm/simulator_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698