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

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

Issue 240283005: Adds simulator debugger and Stop to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 months 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/stub_code.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 <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_ARM64) 10 #if defined(TARGET_ARCH_ARM64)
(...skipping 17 matching lines...) Expand all
28 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at."); 28 DEFINE_FLAG(int, stop_sim_at, 0, "Address 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 // The SimulatorDebugger class is used by the simulator while debugging
39 // simulated MIPS code.
regis 2014/04/16 19:55:43 MIPS -> ARM64
zra 2014/04/16 19:57:42 Done.
40 class SimulatorDebugger {
41 public:
42 explicit SimulatorDebugger(Simulator* sim);
43 ~SimulatorDebugger();
44
45 void Stop(Instr* instr, const char* message);
46 void Debug();
47 char* ReadLine(const char* prompt);
48
49 private:
50 Simulator* sim_;
51
52 bool GetValue(char* desc, int64_t* value);
53 // TODO(zra): GetVValue for doubles.
54 // TODO(zra): Breakpoints.
55 };
56
57
58 SimulatorDebugger::SimulatorDebugger(Simulator* sim) {
59 sim_ = sim;
60 }
61
62
63 SimulatorDebugger::~SimulatorDebugger() {
64 }
65
66 void SimulatorDebugger::Stop(Instr* instr, const char* message) {
67 OS::Print("Simulator hit %s\n", message);
68 Debug();
69 }
70
71
72 static Register LookupCpuRegisterByName(const char* name) {
73 static const char* kNames[] = {
74 "r0", "r1", "r2", "r3",
75 "r4", "r5", "r6", "r7",
76 "r8", "r9", "r10", "r11",
77 "r12", "r13", "r14", "r15",
78 "r16", "r17", "r18", "r19",
79 "r20", "r21", "r22", "r23",
80 "r24", "r25", "r26", "r27",
81 "r28", "r29", "r30",
82
83 "ip0", "ip1", "pp", "ctx", "fp", "lr", "sp", "zr",
84 };
85 static const Register kRegisters[] = {
86 R0, R1, R2, R3, R4, R5, R6, R7,
87 R8, R9, R10, R11, R12, R13, R14, R15,
88 R16, R17, R18, R19, R20, R21, R22, R23,
89 R24, R25, R26, R27, R28, R29, R30,
90
91 IP0, IP1, PP, CTX, FP, LR, SP, ZR,
92 };
93 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters));
94 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) {
95 if (strcmp(kNames[i], name) == 0) {
96 return kRegisters[i];
97 }
98 }
99 return kNoRegister;
100 }
101
102
103 bool SimulatorDebugger::GetValue(char* desc, int64_t* value) {
104 Register reg = LookupCpuRegisterByName(desc);
105 if (reg != kNoRegister) {
106 *value = sim_->get_register(reg);
107 return true;
108 }
109 if (desc[0] == '*') {
110 int64_t addr;
111 if (GetValue(desc + 1, &addr)) {
112 if (Simulator::IsIllegalAddress(addr)) {
113 return false;
114 }
115 *value = *(reinterpret_cast<int64_t*>(addr));
116 return true;
117 }
118 }
119 if (strcmp("pc", desc) == 0) {
120 *value = sim_->get_pc();
121 return true;
122 }
123 bool retval = SScanF(desc, "0x%"Px64, value) == 1;
124 if (!retval) {
125 retval = SScanF(desc, "%"Px64, value) == 1;
126 }
127 return retval;
128 }
129
130
131 void SimulatorDebugger::Debug() {
132 intptr_t last_pc = -1;
133 bool done = false;
134
135 #define COMMAND_SIZE 63
136 #define ARG_SIZE 255
137
138 #define STR(a) #a
139 #define XSTR(a) STR(a)
140
141 char cmd[COMMAND_SIZE + 1];
142 char arg1[ARG_SIZE + 1];
143 char arg2[ARG_SIZE + 1];
144
145 // make sure to have a proper terminating character if reaching the limit
146 cmd[COMMAND_SIZE] = 0;
147 arg1[ARG_SIZE] = 0;
148 arg2[ARG_SIZE] = 0;
149
150 // TODO(zra): Undo all set breakpoints while running in the debugger shell.
151 // This will make them invisible to all commands.
152 // UndoBreakpoints();
153
154 while (!done) {
155 if (last_pc != sim_->get_pc()) {
156 last_pc = sim_->get_pc();
157 if (Simulator::IsIllegalAddress(last_pc)) {
158 OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc);
159 } else {
160 Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
161 }
162 }
163 char* line = ReadLine("sim> ");
164 if (line == NULL) {
165 FATAL("ReadLine failed");
166 } else {
167 // Use sscanf to parse the individual parts of the command line. At the
168 // moment no command expects more than two parameters.
169 int args = SScanF(line,
170 "%" XSTR(COMMAND_SIZE) "s "
171 "%" XSTR(ARG_SIZE) "s "
172 "%" XSTR(ARG_SIZE) "s",
173 cmd, arg1, arg2);
174 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
175 OS::Print("c/cont -- continue execution\n"
176 "disasm -- disassemble instrs at current pc location\n"
177 " other variants are:\n"
178 " disasm <address>\n"
179 " disasm <address> <number_of_instructions>\n"
180 " by default 10 instrs are disassembled\n"
181 "gdb -- transfer control to gdb\n"
182 "h/help -- print this help string\n"
183 "p/print <reg or value or *addr> -- print integer value\n"
184 "po/printobject <*reg or *addr> -- print object\n"
185 "si/stepi -- single step an instruction\n"
186 "q/quit -- Quit the debugger and exit the program\n");
187 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) {
188 OS::Print("Quitting\n");
189 OS::Exit(0);
190 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
191 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
192 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
193 // Execute the one instruction we broke at with breakpoints disabled.
194 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
195 // Leave the debugger shell.
196 done = true;
197 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
198 if (args == 2) {
199 int64_t value;
200 if (GetValue(arg1, &value)) {
201 OS::Print("%s: %"Pu64" 0x%"Px64"\n", arg1, value, value);
202 } else {
203 OS::Print("%s unrecognized\n", arg1);
204 }
205 } else {
206 OS::Print("print <reg or value or *addr>\n");
207 }
208 } else if ((strcmp(cmd, "po") == 0) ||
209 (strcmp(cmd, "printobject") == 0)) {
210 if (args == 2) {
211 int64_t value;
212 // Make the dereferencing '*' optional.
213 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) ||
214 GetValue(arg1, &value)) {
215 if (Isolate::Current()->heap()->Contains(value)) {
216 OS::Print("%s: \n", arg1);
217 #if defined(DEBUG)
218 const Object& obj = Object::Handle(
219 reinterpret_cast<RawObject*>(value));
220 obj.Print();
221 #endif // defined(DEBUG)
222 } else {
223 OS::Print("0x%"Px64" is not an object reference\n", value);
224 }
225 } else {
226 OS::Print("%s unrecognized\n", arg1);
227 }
228 } else {
229 OS::Print("printobject <*reg or *addr>\n");
230 }
231 } else if (strcmp(cmd, "disasm") == 0) {
232 int64_t start = 0;
233 int64_t end = 0;
234 if (args == 1) {
235 start = sim_->get_pc();
236 end = start + (10 * Instr::kInstrSize);
237 } else if (args == 2) {
238 if (GetValue(arg1, &start)) {
239 // no length parameter passed, assume 10 instructions
240 if (Simulator::IsIllegalAddress(start)) {
241 // If start isn't a valid address, warn and use PC instead
242 OS::Print("First argument yields invalid address: 0x%"Px64"\n",
243 start);
244 OS::Print("Using PC instead");
245 start = sim_->get_pc();
246 }
247 end = start + (10 * Instr::kInstrSize);
248 }
249 } else {
250 intptr_t length;
251 if (GetValue(arg1, &start) && GetValue(arg2, &length)) {
252 if (Simulator::IsIllegalAddress(start)) {
253 // If start isn't a valid address, warn and use PC instead
254 OS::Print("First argument yields invalid address: 0x%"Px64"\n",
255 start);
256 OS::Print("Using PC instead\n");
257 start = sim_->get_pc();
258 }
259 end = start + (length * Instr::kInstrSize);
260 }
261 }
262 Disassembler::Disassemble(start, end);
263 } else if (strcmp(cmd, "gdb") == 0) {
264 OS::Print("relinquishing control to gdb\n");
265 OS::DebugBreak();
266 OS::Print("regaining control from gdb\n");
267 } else {
268 OS::Print("Unknown command: %s\n", cmd);
269 }
270 }
271 delete[] line;
272 }
273
274 // TODO(zra): Add all the breakpoints back to stop execution and enter the
275 // debugger shell when hit.
276 // RedoBreakpoints();
277
278 #undef COMMAND_SIZE
279 #undef ARG_SIZE
280
281 #undef STR
282 #undef XSTR
283 }
284
285
286 char* SimulatorDebugger::ReadLine(const char* prompt) {
287 char* result = NULL;
288 char line_buf[256];
289 intptr_t offset = 0;
290 bool keep_going = true;
291 OS::Print("%s", prompt);
292 while (keep_going) {
293 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
294 // fgets got an error. Just give up.
295 if (result != NULL) {
296 delete[] result;
297 }
298 return NULL;
299 }
300 intptr_t len = strlen(line_buf);
301 if (len > 1 &&
302 line_buf[len - 2] == '\\' &&
303 line_buf[len - 1] == '\n') {
304 // When we read a line that ends with a "\" we remove the escape and
305 // append the remainder.
306 line_buf[len - 2] = '\n';
307 line_buf[len - 1] = 0;
308 len -= 1;
309 } else if ((len > 0) && (line_buf[len - 1] == '\n')) {
310 // Since we read a new line we are done reading the line. This
311 // will exit the loop after copying this buffer into the result.
312 keep_going = false;
313 }
314 if (result == NULL) {
315 // Allocate the initial result and make room for the terminating '\0'
316 result = new char[len + 1];
317 if (result == NULL) {
318 // OOM, so cannot readline anymore.
319 return NULL;
320 }
321 } else {
322 // Allocate a new result with enough room for the new addition.
323 intptr_t new_len = offset + len + 1;
324 char* new_result = new char[new_len];
325 if (new_result == NULL) {
326 // OOM, free the buffer allocated so far and return NULL.
327 delete[] result;
328 return NULL;
329 } else {
330 // Copy the existing input into the new array and set the new
331 // array as the result.
332 memmove(new_result, result, offset);
333 delete[] result;
334 result = new_result;
335 }
336 }
337 // Copy the newly read line into the result.
338 memmove(result + offset, line_buf, len);
339 offset += len;
340 }
341 ASSERT(result != NULL);
342 result[offset] = '\0';
343 return result;
344 }
345
346
38 Simulator::Simulator() { 347 Simulator::Simulator() {
39 // Setup simulator support first. Some of this information is needed to 348 // Setup simulator support first. Some of this information is needed to
40 // setup the architecture state. 349 // setup the architecture state.
41 // We allocate the stack here, the size is computed as the sum of 350 // We allocate the stack here, the size is computed as the sum of
42 // the size specified by the user and the buffer space needed for 351 // the size specified by the user and the buffer space needed for
43 // handling stack overflow exceptions. To be safe in potential 352 // handling stack overflow exceptions. To be safe in potential
44 // stack underflows we also add some underflow buffer space. 353 // stack underflows we also add some underflow buffer space.
45 stack_ = new char[(Isolate::GetSpecifiedStackSize() + 354 stack_ = new char[(Isolate::GetSpecifiedStackSize() +
46 Isolate::kStackSizeBuffer + 355 Isolate::kStackSizeBuffer +
47 kSimulatorStackUnderflowSize)]; 356 kSimulatorStackUnderflowSize)];
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 } 919 }
611 const int64_t imm19 = instr->SImm19Field(); 920 const int64_t imm19 = instr->SImm19Field();
612 const int64_t dest = get_pc() + (imm19 << 2); 921 const int64_t dest = get_pc() + (imm19 << 2);
613 if (ConditionallyExecute(instr)) { 922 if (ConditionallyExecute(instr)) {
614 set_pc(dest); 923 set_pc(dest);
615 } 924 }
616 } 925 }
617 926
618 927
619 void Simulator::DecodeExceptionGen(Instr* instr) { 928 void Simulator::DecodeExceptionGen(Instr* instr) {
620 UnimplementedInstruction(instr); 929 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) &&
930 (instr->Bits(21, 3) == 0)) {
931 // Format(instr, "svc 'imm16");
932 UnimplementedInstruction(instr);
933 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
934 (instr->Bits(21, 3) == 1)) {
935 // Format(instr, "brk 'imm16");
936 UnimplementedInstruction(instr);
937 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
938 (instr->Bits(21, 3) == 2)) {
939 // Format(instr, "hlt 'imm16");
940 uint16_t imm = static_cast<uint16_t>(instr->Imm16Field());
941 if (imm == kImmExceptionIsDebug) {
942 SimulatorDebugger dbg(this);
943 const char* message = *reinterpret_cast<const char**>(
944 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
945 set_pc(get_pc() + Instr::kInstrSize);
946 dbg.Stop(instr, message);
947 } else if (imm == kImmExceptionIsPrintf) {
948 const char* message = *reinterpret_cast<const char**>(
949 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
950 OS::Print("Simulator hit: %s", message);
951 } else {
952 UnimplementedInstruction(instr);
953 }
954 }
621 } 955 }
622 956
623 957
624 void Simulator::DecodeSystem(Instr* instr) { 958 void Simulator::DecodeSystem(Instr* instr) {
625 if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) && 959 if ((instr->Bits(0, 8) == 0x5f) && (instr->Bits(12, 4) == 2) &&
626 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) && 960 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) &&
627 (instr->Bit(21) == 0)) { 961 (instr->Bit(21) == 0)) {
628 if (instr->Bits(8, 4) == 0) { 962 if (instr->Bits(8, 4) == 0) {
629 // Format(instr, "nop"); 963 // Format(instr, "nop");
630 } else { 964 } else {
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 int64_t return_value; 1757 int64_t return_value;
1424 return_value = get_register(R0); 1758 return_value = get_register(R0);
1425 return return_value; 1759 return return_value;
1426 } 1760 }
1427 1761
1428 } // namespace dart 1762 } // namespace dart
1429 1763
1430 #endif // !defined(HOST_ARCH_ARM64) 1764 #endif // !defined(HOST_ARCH_ARM64)
1431 1765
1432 #endif // defined TARGET_ARCH_ARM64 1766 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | runtime/vm/stub_code.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698