OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 | 119 |
120 static void InitializeCoverage() { | 120 static void InitializeCoverage() { |
121 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); | 121 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); |
122 if (file_name != NULL) { | 122 if (file_name != NULL) { |
123 coverage_log = fopen(file_name, "aw+"); | 123 coverage_log = fopen(file_name, "aw+"); |
124 } | 124 } |
125 } | 125 } |
126 | 126 |
127 | 127 |
128 void MipsDebugger::Stop(Instruction* instr) { | 128 void MipsDebugger::Stop(Instruction* instr) { |
129 UNIMPLEMENTED_MIPS(); | 129 // Get the stop code. |
130 char* str = reinterpret_cast<char*>(instr->InstructionBits()); | 130 uint32_t code = instr->Bits(25, 6); |
131 if (strlen(str) > 0) { | 131 // Retrieve the encoded address, which comes just after this stop. |
| 132 char** msg_address = |
| 133 reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize); |
| 134 char* msg = *msg_address; |
| 135 ASSERT(msg != NULL); |
| 136 |
| 137 // Update this stop description. |
| 138 if (!watched_stops[code].desc) { |
| 139 watched_stops[code].desc = msg; |
| 140 } |
| 141 |
| 142 if (strlen(msg) > 0) { |
132 if (coverage_log != NULL) { | 143 if (coverage_log != NULL) { |
133 fprintf(coverage_log, "%s\n", str); | 144 fprintf(coverage_log, "%s\n", str); |
134 fflush(coverage_log); | 145 fflush(coverage_log); |
135 } | 146 } |
136 instr->SetInstructionBits(0x0); // Overwrite with nop. | 147 // Overwrite the instruction and address with nops. |
| 148 instr->SetInstructionBits(kNopInstr); |
| 149 reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr); |
137 } | 150 } |
138 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize); | 151 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstructionSize); |
139 } | 152 } |
140 | 153 |
141 | 154 |
142 #else // GENERATED_CODE_COVERAGE | 155 #else // GENERATED_CODE_COVERAGE |
143 | 156 |
144 #define UNSUPPORTED() printf("Unsupported instruction.\n"); | 157 #define UNSUPPORTED() printf("Unsupported instruction.\n"); |
145 | 158 |
146 static void InitializeCoverage() {} | 159 static void InitializeCoverage() {} |
147 | 160 |
148 | 161 |
149 void MipsDebugger::Stop(Instruction* instr) { | 162 void MipsDebugger::Stop(Instruction* instr) { |
150 const char* str = reinterpret_cast<char*>(instr->InstructionBits()); | 163 // Get the stop code. |
151 PrintF("Simulator hit %s\n", str); | 164 uint32_t code = instr->Bits(25, 6); |
152 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize); | 165 // Retrieve the encoded address, which comes just after this stop. |
| 166 char* msg = *reinterpret_cast<char**>(sim_->get_pc() + |
| 167 Instruction::kInstrSize); |
| 168 // Update this stop description. |
| 169 if (!sim_->watched_stops[code].desc) { |
| 170 sim_->watched_stops[code].desc = msg; |
| 171 } |
| 172 PrintF("Simulator hit %s (%u)\n", msg, code); |
| 173 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); |
153 Debug(); | 174 Debug(); |
154 } | 175 } |
155 #endif // GENERATED_CODE_COVERAGE | 176 #endif // GENERATED_CODE_COVERAGE |
156 | 177 |
157 | 178 |
158 int32_t MipsDebugger::GetRegisterValue(int regnum) { | 179 int32_t MipsDebugger::GetRegisterValue(int regnum) { |
159 if (regnum == kNumSimuRegisters) { | 180 if (regnum == kNumSimuRegisters) { |
160 return sim_->get_pc(); | 181 return sim_->get_pc(); |
161 } else { | 182 } else { |
162 return sim_->get_register(regnum); | 183 return sim_->get_register(regnum); |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 } | 599 } |
579 } else { | 600 } else { |
580 PrintF("break <address>\n"); | 601 PrintF("break <address>\n"); |
581 } | 602 } |
582 } else if (strcmp(cmd, "del") == 0) { | 603 } else if (strcmp(cmd, "del") == 0) { |
583 if (!DeleteBreakpoint(NULL)) { | 604 if (!DeleteBreakpoint(NULL)) { |
584 PrintF("deleting breakpoint failed\n"); | 605 PrintF("deleting breakpoint failed\n"); |
585 } | 606 } |
586 } else if (strcmp(cmd, "flags") == 0) { | 607 } else if (strcmp(cmd, "flags") == 0) { |
587 PrintF("No flags on MIPS !\n"); | 608 PrintF("No flags on MIPS !\n"); |
588 } else if (strcmp(cmd, "unstop") == 0) { | 609 } else if (strcmp(cmd, "stop") == 0) { |
589 PrintF("Unstop command not implemented on MIPS."); | 610 int32_t value; |
| 611 intptr_t stop_pc = sim_->get_pc() - |
| 612 2 * Instruction::kInstrSize; |
| 613 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc); |
| 614 Instruction* msg_address = |
| 615 reinterpret_cast<Instruction*>(stop_pc + |
| 616 Instruction::kInstrSize); |
| 617 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) { |
| 618 // Remove the current stop. |
| 619 if (sim_->isStopInstruction(stop_instr)) { |
| 620 stop_instr->SetInstructionBits(kNopInstr); |
| 621 msg_address->SetInstructionBits(kNopInstr); |
| 622 } else { |
| 623 PrintF("Not at debugger stop.\n"); |
| 624 } |
| 625 } else if (argc == 3) { |
| 626 // Print information about all/the specified breakpoint(s). |
| 627 if (strcmp(arg1, "info") == 0) { |
| 628 if (strcmp(arg2, "all") == 0) { |
| 629 PrintF("Stop information:\n"); |
| 630 for (uint32_t i = kMaxWatchpointCode + 1; |
| 631 i <= kMaxStopCode; |
| 632 i++) { |
| 633 sim_->PrintStopInfo(i); |
| 634 } |
| 635 } else if (GetValue(arg2, &value)) { |
| 636 sim_->PrintStopInfo(value); |
| 637 } else { |
| 638 PrintF("Unrecognized argument.\n"); |
| 639 } |
| 640 } else if (strcmp(arg1, "enable") == 0) { |
| 641 // Enable all/the specified breakpoint(s). |
| 642 if (strcmp(arg2, "all") == 0) { |
| 643 for (uint32_t i = kMaxWatchpointCode + 1; |
| 644 i <= kMaxStopCode; |
| 645 i++) { |
| 646 sim_->EnableStop(i); |
| 647 } |
| 648 } else if (GetValue(arg2, &value)) { |
| 649 sim_->EnableStop(value); |
| 650 } else { |
| 651 PrintF("Unrecognized argument.\n"); |
| 652 } |
| 653 } else if (strcmp(arg1, "disable") == 0) { |
| 654 // Disable all/the specified breakpoint(s). |
| 655 if (strcmp(arg2, "all") == 0) { |
| 656 for (uint32_t i = kMaxWatchpointCode + 1; |
| 657 i <= kMaxStopCode; |
| 658 i++) { |
| 659 sim_->DisableStop(i); |
| 660 } |
| 661 } else if (GetValue(arg2, &value)) { |
| 662 sim_->DisableStop(value); |
| 663 } else { |
| 664 PrintF("Unrecognized argument.\n"); |
| 665 } |
| 666 } |
| 667 } else { |
| 668 PrintF("Wrong usage. Use help command for more information.\n"); |
| 669 } |
590 } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) { | 670 } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) { |
591 // Print registers and disassemble. | 671 // Print registers and disassemble. |
592 PrintAllRegs(); | 672 PrintAllRegs(); |
593 PrintF("\n"); | 673 PrintF("\n"); |
594 | 674 |
595 disasm::NameConverter converter; | 675 disasm::NameConverter converter; |
596 disasm::Disassembler dasm(converter); | 676 disasm::Disassembler dasm(converter); |
597 // Use a reasonably large buffer. | 677 // Use a reasonably large buffer. |
598 v8::internal::EmbeddedVector<char, 256> buffer; | 678 v8::internal::EmbeddedVector<char, 256> buffer; |
599 | 679 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 PrintF("disasm [<address/register>]\n"); | 725 PrintF("disasm [<address/register>]\n"); |
646 PrintF("disasm [[<address/register>] <instructions>]\n"); | 726 PrintF("disasm [[<address/register>] <instructions>]\n"); |
647 PrintF(" disassemble code, default is 10 instructions\n"); | 727 PrintF(" disassemble code, default is 10 instructions\n"); |
648 PrintF(" from pc (alias 'di')\n"); | 728 PrintF(" from pc (alias 'di')\n"); |
649 PrintF("gdb\n"); | 729 PrintF("gdb\n"); |
650 PrintF(" enter gdb\n"); | 730 PrintF(" enter gdb\n"); |
651 PrintF("break <address>\n"); | 731 PrintF("break <address>\n"); |
652 PrintF(" set a break point on the address\n"); | 732 PrintF(" set a break point on the address\n"); |
653 PrintF("del\n"); | 733 PrintF("del\n"); |
654 PrintF(" delete the breakpoint\n"); | 734 PrintF(" delete the breakpoint\n"); |
655 PrintF("unstop\n"); | 735 PrintF("stop feature:\n"); |
656 PrintF(" ignore the stop instruction at the current location"); | 736 PrintF(" Description:\n"); |
657 PrintF(" from now on\n"); | 737 PrintF(" Stops are debug instructions inserted by\n"); |
| 738 PrintF(" the Assembler::stop() function.\n"); |
| 739 PrintF(" When hitting a stop, the Simulator will\n"); |
| 740 PrintF(" stop and and give control to the Debugger.\n"); |
| 741 PrintF(" All stop codes are watched:\n"); |
| 742 PrintF(" - They can be enabled / disabled: the Simulator\n"); |
| 743 PrintF(" will / won't stop when hitting them.\n"); |
| 744 PrintF(" - The Simulator keeps track of how many times they \n"); |
| 745 PrintF(" are met. (See the info command.) Going over a\n"); |
| 746 PrintF(" disabled stop still increases its counter. \n"); |
| 747 PrintF(" Commands:\n"); |
| 748 PrintF(" stop info all/<code> : print infos about number <code>\n"); |
| 749 PrintF(" or all stop(s).\n"); |
| 750 PrintF(" stop enable/disable all/<code> : enables / disables\n"); |
| 751 PrintF(" all or number <code> stop(s)\n"); |
| 752 PrintF(" stop unstop\n"); |
| 753 PrintF(" ignore the stop instruction at the current location\n"); |
| 754 PrintF(" from now on\n"); |
658 } else { | 755 } else { |
659 PrintF("Unknown command: %s\n", cmd); | 756 PrintF("Unknown command: %s\n", cmd); |
660 } | 757 } |
661 } | 758 } |
662 DeleteArray(line); | 759 DeleteArray(line); |
663 } | 760 } |
664 | 761 |
665 // Add all the breakpoints back to stop execution and enter the debugger | 762 // Add all the breakpoints back to stop execution and enter the debugger |
666 // shell when hit. | 763 // shell when hit. |
667 RedoBreakpoints(); | 764 RedoBreakpoints(); |
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1281 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, | 1378 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, |
1282 int32_t arg1); | 1379 int32_t arg1); |
1283 | 1380 |
1284 // Software interrupt instructions are used by the simulator to call into the | 1381 // Software interrupt instructions are used by the simulator to call into the |
1285 // C-based V8 runtime. They are also used for debugging with simulator. | 1382 // C-based V8 runtime. They are also used for debugging with simulator. |
1286 void Simulator::SoftwareInterrupt(Instruction* instr) { | 1383 void Simulator::SoftwareInterrupt(Instruction* instr) { |
1287 // There are several instructions that could get us here, | 1384 // There are several instructions that could get us here, |
1288 // the break_ instruction, or several variants of traps. All | 1385 // the break_ instruction, or several variants of traps. All |
1289 // Are "SPECIAL" class opcode, and are distinuished by function. | 1386 // Are "SPECIAL" class opcode, and are distinuished by function. |
1290 int32_t func = instr->FunctionFieldRaw(); | 1387 int32_t func = instr->FunctionFieldRaw(); |
1291 int32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1; | 1388 uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1; |
1292 | 1389 |
1293 // We first check if we met a call_rt_redirected. | 1390 // We first check if we met a call_rt_redirected. |
1294 if (instr->InstructionBits() == rtCallRedirInstr) { | 1391 if (instr->InstructionBits() == rtCallRedirInstr) { |
1295 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1392 Redirection* redirection = Redirection::FromSwiInstruction(instr); |
1296 int32_t arg0 = get_register(a0); | 1393 int32_t arg0 = get_register(a0); |
1297 int32_t arg1 = get_register(a1); | 1394 int32_t arg1 = get_register(a1); |
1298 int32_t arg2 = get_register(a2); | 1395 int32_t arg2 = get_register(a2); |
1299 int32_t arg3 = get_register(a3); | 1396 int32_t arg3 = get_register(a3); |
1300 int32_t arg4 = 0; | 1397 int32_t arg4 = 0; |
1301 int32_t arg5 = 0; | 1398 int32_t arg5 = 0; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1433 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); | 1530 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); |
1434 set_register(v0, static_cast<int32_t>(result)); | 1531 set_register(v0, static_cast<int32_t>(result)); |
1435 set_register(v1, static_cast<int32_t>(result >> 32)); | 1532 set_register(v1, static_cast<int32_t>(result >> 32)); |
1436 } | 1533 } |
1437 if (::v8::internal::FLAG_trace_sim) { | 1534 if (::v8::internal::FLAG_trace_sim) { |
1438 PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0)); | 1535 PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0)); |
1439 } | 1536 } |
1440 set_register(ra, saved_ra); | 1537 set_register(ra, saved_ra); |
1441 set_pc(get_register(ra)); | 1538 set_pc(get_register(ra)); |
1442 | 1539 |
1443 } else if (func == BREAK && code >= 0 && code < 32) { | 1540 } else if (func == BREAK && code <= kMaxStopCode) { |
1444 // First 32 break_ codes interpreted as debug-markers/watchpoints. | 1541 if (isWatchpoint(code)) { |
1445 MipsDebugger dbg(this); | 1542 PrintWatchpoint(code); |
1446 ++break_count_; | 1543 } else { |
1447 PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------" | 1544 IncreaseStopCounter(code); |
1448 "----------------------------------", | 1545 HandleStop(code, instr); |
1449 code, break_count_, icount_); | 1546 } |
1450 dbg.PrintAllRegs(); // Print registers and continue running. | |
1451 } else { | 1547 } else { |
1452 // All remaining break_ codes, and all traps are handled here. | 1548 // All remaining break_ codes, and all traps are handled here. |
1453 MipsDebugger dbg(this); | 1549 MipsDebugger dbg(this); |
1454 dbg.Debug(); | 1550 dbg.Debug(); |
1455 } | 1551 } |
1456 } | 1552 } |
1457 | 1553 |
1458 | 1554 |
| 1555 // Stop helper functions. |
| 1556 bool Simulator::isWatchpoint(uint32_t code) { |
| 1557 return (code <= kMaxWatchpointCode); |
| 1558 } |
| 1559 |
| 1560 |
| 1561 void Simulator::PrintWatchpoint(uint32_t code) { |
| 1562 MipsDebugger dbg(this); |
| 1563 ++break_count_; |
| 1564 PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------" |
| 1565 "----------------------------------", |
| 1566 code, break_count_, icount_); |
| 1567 dbg.PrintAllRegs(); // Print registers and continue running. |
| 1568 } |
| 1569 |
| 1570 |
| 1571 void Simulator::HandleStop(uint32_t code, Instruction* instr) { |
| 1572 // Stop if it is enabled, otherwise go on jumping over the stop |
| 1573 // and the message address. |
| 1574 if (isEnabledStop(code)) { |
| 1575 MipsDebugger dbg(this); |
| 1576 dbg.Stop(instr); |
| 1577 } else { |
| 1578 set_pc(get_pc() + 2 * Instruction::kInstrSize); |
| 1579 } |
| 1580 } |
| 1581 |
| 1582 |
| 1583 bool Simulator::isStopInstruction(Instruction* instr) { |
| 1584 int32_t func = instr->FunctionFieldRaw(); |
| 1585 uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6)); |
| 1586 return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode; |
| 1587 } |
| 1588 |
| 1589 |
| 1590 bool Simulator::isEnabledStop(uint32_t code) { |
| 1591 ASSERT(code <= kMaxStopCode); |
| 1592 ASSERT(code > kMaxWatchpointCode); |
| 1593 return !(watched_stops[code].count & kStopDisabledBit); |
| 1594 } |
| 1595 |
| 1596 |
| 1597 void Simulator::EnableStop(uint32_t code) { |
| 1598 if (!isEnabledStop(code)) { |
| 1599 watched_stops[code].count &= ~kStopDisabledBit; |
| 1600 } |
| 1601 } |
| 1602 |
| 1603 |
| 1604 void Simulator::DisableStop(uint32_t code) { |
| 1605 if (isEnabledStop(code)) { |
| 1606 watched_stops[code].count |= kStopDisabledBit; |
| 1607 } |
| 1608 } |
| 1609 |
| 1610 |
| 1611 void Simulator::IncreaseStopCounter(uint32_t code) { |
| 1612 ASSERT(code <= kMaxStopCode); |
| 1613 if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) { |
| 1614 PrintF("Stop counter for code %i has overflowed.\n" |
| 1615 "Enabling this code and reseting the counter to 0.\n", code); |
| 1616 watched_stops[code].count = 0; |
| 1617 EnableStop(code); |
| 1618 } else { |
| 1619 watched_stops[code].count++; |
| 1620 } |
| 1621 } |
| 1622 |
| 1623 |
| 1624 // Print a stop status. |
| 1625 void Simulator::PrintStopInfo(uint32_t code) { |
| 1626 if (code <= kMaxWatchpointCode) { |
| 1627 PrintF("That is a watchpoint, not a stop.\n"); |
| 1628 return; |
| 1629 } else if (code > kMaxStopCode) { |
| 1630 PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1); |
| 1631 return; |
| 1632 } |
| 1633 const char* state = isEnabledStop(code) ? "Enabled" : "Disabled"; |
| 1634 int32_t count = watched_stops[code].count & ~kStopDisabledBit; |
| 1635 // Don't print the state of unused breakpoints. |
| 1636 if (count != 0) { |
| 1637 if (watched_stops[code].desc) { |
| 1638 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n", |
| 1639 code, code, state, count, watched_stops[code].desc); |
| 1640 } else { |
| 1641 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n", |
| 1642 code, code, state, count); |
| 1643 } |
| 1644 } |
| 1645 } |
| 1646 |
| 1647 |
1459 void Simulator::SignalExceptions() { | 1648 void Simulator::SignalExceptions() { |
1460 for (int i = 1; i < kNumExceptions; i++) { | 1649 for (int i = 1; i < kNumExceptions; i++) { |
1461 if (exceptions[i] != 0) { | 1650 if (exceptions[i] != 0) { |
1462 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i); | 1651 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i); |
1463 } | 1652 } |
1464 } | 1653 } |
1465 } | 1654 } |
1466 | 1655 |
1467 | 1656 |
1468 // Handle execution based on instruction types. | 1657 // Handle execution based on instruction types. |
(...skipping 1143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2612 } | 2801 } |
2613 | 2802 |
2614 | 2803 |
2615 #undef UNSUPPORTED | 2804 #undef UNSUPPORTED |
2616 | 2805 |
2617 } } // namespace v8::internal | 2806 } } // namespace v8::internal |
2618 | 2807 |
2619 #endif // USE_SIMULATOR | 2808 #endif // USE_SIMULATOR |
2620 | 2809 |
2621 #endif // V8_TARGET_ARCH_MIPS | 2810 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |