OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
63 void Debug(); | 63 void Debug(); |
64 | 64 |
65 private: | 65 private: |
66 static const instr_t kBreakpointInstr = | 66 static const instr_t kBreakpointInstr = |
67 ((AL << 28) | (7 << 25) | (1 << 24) | break_point); | 67 ((AL << 28) | (7 << 25) | (1 << 24) | break_point); |
68 static const instr_t kNopInstr = | 68 static const instr_t kNopInstr = |
69 ((AL << 28) | (13 << 21)); | 69 ((AL << 28) | (13 << 21)); |
70 | 70 |
71 Simulator* sim_; | 71 Simulator* sim_; |
72 | 72 |
73 bool GetValue(char* desc, int32_t* value); | 73 bool GetValue(const char* desc, int32_t* value); |
74 | 74 |
75 // Set or delete a breakpoint. Returns true if successful. | 75 // Set or delete a breakpoint. Returns true if successful. |
76 bool SetBreakpoint(Instr* breakpc); | 76 bool SetBreakpoint(Instr* breakpc); |
77 bool DeleteBreakpoint(Instr* breakpc); | 77 bool DeleteBreakpoint(Instr* breakpc); |
78 | 78 |
79 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 79 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
80 // execution to skip past breakpoints when run from the debugger. | 80 // execution to skip past breakpoints when run from the debugger. |
81 void UndoBreakpoints(); | 81 void UndoBreakpoints(); |
82 void RedoBreakpoints(); | 82 void RedoBreakpoints(); |
83 }; | 83 }; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
125 | 125 |
126 void Debugger::Stop(Instr* instr) { | 126 void Debugger::Stop(Instr* instr) { |
127 const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff); | 127 const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff); |
128 PrintF("Simulator hit %s\n", str); | 128 PrintF("Simulator hit %s\n", str); |
129 sim_->set_pc(sim_->get_pc() + Instr::kInstrSize); | 129 sim_->set_pc(sim_->get_pc() + Instr::kInstrSize); |
130 Debug(); | 130 Debug(); |
131 } | 131 } |
132 #endif | 132 #endif |
133 | 133 |
134 | 134 |
135 // The order of these are important, see the handling of the 'print all' | |
136 // debugger command. | |
135 static const char* reg_names[] = { "r0", "r1", "r2", "r3", | 137 static const char* reg_names[] = { "r0", "r1", "r2", "r3", |
136 "r4", "r5", "r6", "r7", | 138 "r4", "r5", "r6", "r7", |
137 "r8", "r9", "r10", "r11", | 139 "r8", "r9", "r10", "r11", |
138 "r12", "r13", "r14", "r15", | 140 "r12", "r13", "r14", "r15", |
139 "pc", "lr", "sp", "ip", | 141 "pc", "lr", "sp", "ip", |
140 "fp", "sl", ""}; | 142 "fp", "sl", ""}; |
141 | 143 |
142 static int reg_nums[] = { 0, 1, 2, 3, | 144 static int reg_nums[] = { 0, 1, 2, 3, |
143 4, 5, 6, 7, | 145 4, 5, 6, 7, |
144 8, 9, 10, 11, | 146 8, 9, 10, 11, |
145 12, 13, 14, 15, | 147 12, 13, 14, 15, |
146 15, 14, 13, 12, | 148 15, 14, 13, 12, |
147 11, 10}; | 149 11, 10}; |
148 | 150 |
149 | 151 |
150 static int RegNameToRegNum(char* name) { | 152 static int RegNameToRegNum(const char* name) { |
151 int reg = 0; | 153 int reg = 0; |
152 while (*reg_names[reg] != 0) { | 154 while (*reg_names[reg] != 0) { |
153 if (strcmp(reg_names[reg], name) == 0) { | 155 if (strcmp(reg_names[reg], name) == 0) { |
154 return reg_nums[reg]; | 156 return reg_nums[reg]; |
155 } | 157 } |
156 reg++; | 158 reg++; |
157 } | 159 } |
158 return -1; | 160 return -1; |
159 } | 161 } |
160 | 162 |
161 | 163 |
162 bool Debugger::GetValue(char* desc, int32_t* value) { | 164 bool Debugger::GetValue(const char* desc, int32_t* value) { |
163 int regnum = RegNameToRegNum(desc); | 165 int regnum = RegNameToRegNum(desc); |
164 if (regnum >= 0) { | 166 if (regnum >= 0) { |
165 if (regnum == 15) { | 167 if (regnum == 15) { |
166 *value = sim_->get_pc(); | 168 *value = sim_->get_pc(); |
167 } else { | 169 } else { |
168 *value = sim_->get_register(regnum); | 170 *value = sim_->get_register(regnum); |
169 } | 171 } |
170 return true; | 172 return true; |
171 } else { | 173 } else { |
172 return SScanF(desc, "%i", value) == 1; | 174 return SScanF(desc, "%i", value) == 1; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 265 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
264 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 266 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
265 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 267 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
266 // Execute the one instruction we broke at with breakpoints disabled. | 268 // Execute the one instruction we broke at with breakpoints disabled. |
267 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 269 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
268 // Leave the debugger shell. | 270 // Leave the debugger shell. |
269 done = true; | 271 done = true; |
270 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 272 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
271 if (args == 2) { | 273 if (args == 2) { |
272 int32_t value; | 274 int32_t value; |
273 if (GetValue(arg1, &value)) { | 275 if (strcmp(arg1, "all") == 0) { |
274 PrintF("%s: %d 0x%x\n", arg1, value, value); | 276 for (int i = 0; i <= 15; i++) { |
iposva
2009/09/04 05:30:24
Please use named constants here.
| |
277 if (GetValue(reg_names[i], &value)) { | |
278 if (i <= 10) { | |
iposva
2009/09/04 05:30:24
and here.
| |
279 PrintF("%s: 08x%x %d\n", reg_names[i], value, value); | |
280 } else { | |
281 PrintF("%s: 08x%x %d\n", reg_names[15 + 16 - i], value, value) ; | |
iposva
2009/09/04 05:30:24
and here.
Better yet, abstract the register to na
| |
282 } | |
283 } | |
284 } | |
275 } else { | 285 } else { |
276 PrintF("%s unrecognized\n", arg1); | 286 if (GetValue(arg1, &value)) { |
287 PrintF("%s: 08x%x %d \n", arg1, value, value); | |
288 } else { | |
289 PrintF("%s unrecognized\n", arg1); | |
290 } | |
277 } | 291 } |
278 } else { | 292 } else { |
279 PrintF("print value\n"); | 293 PrintF("print <register>\n"); |
280 } | 294 } |
281 } else if ((strcmp(cmd, "po") == 0) | 295 } else if ((strcmp(cmd, "po") == 0) |
282 || (strcmp(cmd, "printobject") == 0)) { | 296 || (strcmp(cmd, "printobject") == 0)) { |
283 if (args == 2) { | 297 if (args == 2) { |
284 int32_t value; | 298 int32_t value; |
285 if (GetValue(arg1, &value)) { | 299 if (GetValue(arg1, &value)) { |
286 Object* obj = reinterpret_cast<Object*>(value); | 300 Object* obj = reinterpret_cast<Object*>(value); |
287 USE(obj); | 301 USE(obj); |
iposva
2009/09/04 05:30:24
This USE can be dropped now, that obj is used in D
| |
288 PrintF("%s: \n", arg1); | 302 PrintF("%s: \n", arg1); |
289 #if defined(DEBUG) | 303 #ifdef DEBUG |
290 obj->PrintLn(); | 304 obj->PrintLn(); |
291 #endif // defined(DEBUG) | 305 #else |
306 obj->ShortPrint(); | |
307 PrintF("\n"); | |
308 #endif | |
292 } else { | 309 } else { |
293 PrintF("%s unrecognized\n", arg1); | 310 PrintF("%s unrecognized\n", arg1); |
294 } | 311 } |
295 } else { | 312 } else { |
296 PrintF("printobject value\n"); | 313 PrintF("printobject <value>\n"); |
297 } | 314 } |
298 } else if (strcmp(cmd, "disasm") == 0) { | 315 } else if (strcmp(cmd, "disasm") == 0) { |
299 disasm::NameConverter converter; | 316 disasm::NameConverter converter; |
300 disasm::Disassembler dasm(converter); | 317 disasm::Disassembler dasm(converter); |
301 // use a reasonably large buffer | 318 // use a reasonably large buffer |
302 v8::internal::EmbeddedVector<char, 256> buffer; | 319 v8::internal::EmbeddedVector<char, 256> buffer; |
303 | 320 |
304 byte* cur = NULL; | 321 byte* cur = NULL; |
305 byte* end = NULL; | 322 byte* end = NULL; |
306 | 323 |
(...skipping 29 matching lines...) Expand all Loading... | |
336 if (args == 2) { | 353 if (args == 2) { |
337 int32_t value; | 354 int32_t value; |
338 if (GetValue(arg1, &value)) { | 355 if (GetValue(arg1, &value)) { |
339 if (!SetBreakpoint(reinterpret_cast<Instr*>(value))) { | 356 if (!SetBreakpoint(reinterpret_cast<Instr*>(value))) { |
340 PrintF("setting breakpoint failed\n"); | 357 PrintF("setting breakpoint failed\n"); |
341 } | 358 } |
342 } else { | 359 } else { |
343 PrintF("%s unrecognized\n", arg1); | 360 PrintF("%s unrecognized\n", arg1); |
344 } | 361 } |
345 } else { | 362 } else { |
346 PrintF("break addr\n"); | 363 PrintF("break <address>\n"); |
347 } | 364 } |
348 } else if (strcmp(cmd, "del") == 0) { | 365 } else if (strcmp(cmd, "del") == 0) { |
349 if (!DeleteBreakpoint(NULL)) { | 366 if (!DeleteBreakpoint(NULL)) { |
350 PrintF("deleting breakpoint failed\n"); | 367 PrintF("deleting breakpoint failed\n"); |
351 } | 368 } |
352 } else if (strcmp(cmd, "flags") == 0) { | 369 } else if (strcmp(cmd, "flags") == 0) { |
353 PrintF("N flag: %d; ", sim_->n_flag_); | 370 PrintF("N flag: %d; ", sim_->n_flag_); |
354 PrintF("Z flag: %d; ", sim_->z_flag_); | 371 PrintF("Z flag: %d; ", sim_->z_flag_); |
355 PrintF("C flag: %d; ", sim_->c_flag_); | 372 PrintF("C flag: %d; ", sim_->c_flag_); |
356 PrintF("V flag: %d\n", sim_->v_flag_); | 373 PrintF("V flag: %d\n", sim_->v_flag_); |
357 } else if (strcmp(cmd, "unstop") == 0) { | 374 } else if (strcmp(cmd, "unstop") == 0) { |
358 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; | 375 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; |
359 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); | 376 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); |
360 if (stop_instr->ConditionField() == special_condition) { | 377 if (stop_instr->ConditionField() == special_condition) { |
361 stop_instr->SetInstructionBits(kNopInstr); | 378 stop_instr->SetInstructionBits(kNopInstr); |
362 } else { | 379 } else { |
363 PrintF("Not at debugger stop."); | 380 PrintF("Not at debugger stop."); |
364 } | 381 } |
382 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { | |
383 PrintF("print <register>\n"); | |
Erik Corry
2009/09/02 14:22:44
It would be nice to include si/stepi and c/cont as
Søren Thygesen Gjesse
2009/09/02 14:47:19
Added missing commands and description and alias a
| |
384 PrintF("printobject <register>\n"); | |
385 PrintF("flags\n"); | |
386 PrintF("disasm <value>\n"); | |
387 PrintF("gdb\n"); | |
388 PrintF("break <address>\n"); | |
389 PrintF("del\n"); | |
390 PrintF("unstop\n"); | |
365 } else { | 391 } else { |
366 PrintF("Unknown command: %s\n", cmd); | 392 PrintF("Unknown command: %s\n", cmd); |
367 } | 393 } |
368 } | 394 } |
369 DeleteArray(line); | 395 DeleteArray(line); |
370 } | 396 } |
371 | 397 |
372 // Add all the breakpoints back to stop execution and enter the debugger | 398 // Add all the breakpoints back to stop execution and enter the debugger |
373 // shell when hit. | 399 // shell when hit. |
374 RedoBreakpoints(); | 400 RedoBreakpoints(); |
(...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1719 default: { | 1745 default: { |
1720 // The PU field is a 2-bit field. | 1746 // The PU field is a 2-bit field. |
1721 UNREACHABLE(); | 1747 UNREACHABLE(); |
1722 break; | 1748 break; |
1723 } | 1749 } |
1724 } | 1750 } |
1725 // Not sign extending, so load as unsigned. | 1751 // Not sign extending, so load as unsigned. |
1726 uint16_t halfword = ReadH(addr, instr); | 1752 uint16_t halfword = ReadH(addr, instr); |
1727 set_register(rd, halfword); | 1753 set_register(rd, halfword); |
1728 } else { | 1754 } else { |
1729 UNIMPLEMENTED(); | 1755 Debugger dbg(this); |
1756 dbg.Stop(instr); | |
1730 } | 1757 } |
1731 } | 1758 } |
1732 | 1759 |
1733 | 1760 |
1734 // Executes the current instruction. | 1761 // Executes the current instruction. |
1735 void Simulator::InstructionDecode(Instr* instr) { | 1762 void Simulator::InstructionDecode(Instr* instr) { |
1736 pc_modified_ = false; | 1763 pc_modified_ = false; |
1737 if (::v8::internal::FLAG_trace_sim) { | 1764 if (::v8::internal::FLAG_trace_sim) { |
1738 disasm::NameConverter converter; | 1765 disasm::NameConverter converter; |
1739 disasm::Disassembler dasm(converter); | 1766 disasm::Disassembler dasm(converter); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1906 CHECK_EQ(entry_stack, get_register(sp)); | 1933 CHECK_EQ(entry_stack, get_register(sp)); |
1907 set_register(sp, original_stack); | 1934 set_register(sp, original_stack); |
1908 | 1935 |
1909 int32_t result = get_register(r0); | 1936 int32_t result = get_register(r0); |
1910 return result; | 1937 return result; |
1911 } | 1938 } |
1912 | 1939 |
1913 } } // namespace assembler::arm | 1940 } } // namespace assembler::arm |
1914 | 1941 |
1915 #endif // !defined(__arm__) | 1942 #endif // !defined(__arm__) |
OLD | NEW |