OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdarg.h> | 5 #include <stdarg.h> |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #if V8_TARGET_ARCH_ARM | 9 #if V8_TARGET_ARCH_ARM |
10 | 10 |
(...skipping 15 matching lines...) Expand all Loading... |
26 // SScanF not being implemented in a platform independent way through | 26 // SScanF not being implemented in a platform independent way through |
27 // ::v8::internal::OS in the same way as SNPrintF is that the | 27 // ::v8::internal::OS in the same way as SNPrintF is that the |
28 // Windows C Run-Time Library does not provide vsscanf. | 28 // Windows C Run-Time Library does not provide vsscanf. |
29 #define SScanF sscanf // NOLINT | 29 #define SScanF sscanf // NOLINT |
30 | 30 |
31 // The ArmDebugger class is used by the simulator while debugging simulated ARM | 31 // The ArmDebugger class is used by the simulator while debugging simulated ARM |
32 // code. | 32 // code. |
33 class ArmDebugger { | 33 class ArmDebugger { |
34 public: | 34 public: |
35 explicit ArmDebugger(Simulator* sim) : sim_(sim) { } | 35 explicit ArmDebugger(Simulator* sim) : sim_(sim) { } |
36 ~ArmDebugger(); | |
37 | 36 |
38 void Stop(Instruction* instr); | 37 void Stop(Instruction* instr); |
39 void Debug(); | 38 void Debug(); |
40 | 39 |
41 private: | 40 private: |
42 static const Instr kBreakpointInstr = | 41 static const Instr kBreakpointInstr = |
43 (al | (7*B25) | (1*B24) | kBreakpoint); | 42 (al | (7*B25) | (1*B24) | kBreakpoint); |
44 static const Instr kNopInstr = (al | (13*B21)); | 43 static const Instr kNopInstr = (al | (13*B21)); |
45 | 44 |
46 Simulator* sim_; | 45 Simulator* sim_; |
47 | 46 |
48 int32_t GetRegisterValue(int regnum); | 47 int32_t GetRegisterValue(int regnum); |
49 double GetRegisterPairDoubleValue(int regnum); | 48 double GetRegisterPairDoubleValue(int regnum); |
50 double GetVFPDoubleRegisterValue(int regnum); | 49 double GetVFPDoubleRegisterValue(int regnum); |
51 bool GetValue(const char* desc, int32_t* value); | 50 bool GetValue(const char* desc, int32_t* value); |
52 bool GetVFPSingleValue(const char* desc, float* value); | 51 bool GetVFPSingleValue(const char* desc, float* value); |
53 bool GetVFPDoubleValue(const char* desc, double* value); | 52 bool GetVFPDoubleValue(const char* desc, double* value); |
54 | 53 |
55 // Set or delete a breakpoint. Returns true if successful. | 54 // Set or delete a breakpoint. Returns true if successful. |
56 bool SetBreakpoint(Instruction* breakpc); | 55 bool SetBreakpoint(Instruction* breakpc); |
57 bool DeleteBreakpoint(Instruction* breakpc); | 56 bool DeleteBreakpoint(Instruction* breakpc); |
58 | 57 |
59 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 58 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
60 // execution to skip past breakpoints when run from the debugger. | 59 // execution to skip past breakpoints when run from the debugger. |
61 void UndoBreakpoints(); | 60 void UndoBreakpoints(); |
62 void RedoBreakpoints(); | 61 void RedoBreakpoints(); |
63 }; | 62 }; |
64 | 63 |
65 | |
66 ArmDebugger::~ArmDebugger() { | |
67 } | |
68 | |
69 | |
70 | |
71 #ifdef GENERATED_CODE_COVERAGE | |
72 static FILE* coverage_log = NULL; | |
73 | |
74 | |
75 static void InitializeCoverage() { | |
76 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); | |
77 if (file_name != NULL) { | |
78 coverage_log = fopen(file_name, "aw+"); | |
79 } | |
80 } | |
81 | |
82 | |
83 void ArmDebugger::Stop(Instruction* instr) { | 64 void ArmDebugger::Stop(Instruction* instr) { |
84 // Get the stop code. | 65 // Get the stop code. |
85 uint32_t code = instr->SvcValue() & kStopCodeMask; | 66 uint32_t code = instr->SvcValue() & kStopCodeMask; |
86 // Retrieve the encoded address, which comes just after this stop. | |
87 char** msg_address = | |
88 reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize); | |
89 char* msg = *msg_address; | |
90 DCHECK(msg != NULL); | |
91 | |
92 // Update this stop description. | |
93 if (isWatchedStop(code) && !watched_stops_[code].desc) { | |
94 watched_stops_[code].desc = msg; | |
95 } | |
96 | |
97 if (strlen(msg) > 0) { | |
98 if (coverage_log != NULL) { | |
99 fprintf(coverage_log, "%s\n", msg); | |
100 fflush(coverage_log); | |
101 } | |
102 // Overwrite the instruction and address with nops. | |
103 instr->SetInstructionBits(kNopInstr); | |
104 reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr); | |
105 } | |
106 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); | |
107 } | |
108 | |
109 #else // ndef GENERATED_CODE_COVERAGE | |
110 | |
111 static void InitializeCoverage() { | |
112 } | |
113 | |
114 | |
115 void ArmDebugger::Stop(Instruction* instr) { | |
116 // Get the stop code. | |
117 uint32_t code = instr->SvcValue() & kStopCodeMask; | |
118 // Retrieve the encoded address, which comes just after this stop. | 67 // Retrieve the encoded address, which comes just after this stop. |
119 char* msg = *reinterpret_cast<char**>(sim_->get_pc() | 68 char* msg = *reinterpret_cast<char**>(sim_->get_pc() |
120 + Instruction::kInstrSize); | 69 + Instruction::kInstrSize); |
121 // Update this stop description. | 70 // Update this stop description. |
122 if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) { | 71 if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) { |
123 sim_->watched_stops_[code].desc = msg; | 72 sim_->watched_stops_[code].desc = msg; |
124 } | 73 } |
125 // Print the stop message and code if it is not the default code. | 74 // Print the stop message and code if it is not the default code. |
126 if (code != kMaxStopCode) { | 75 if (code != kMaxStopCode) { |
127 PrintF("Simulator hit stop %u: %s\n", code, msg); | 76 PrintF("Simulator hit stop %u: %s\n", code, msg); |
128 } else { | 77 } else { |
129 PrintF("Simulator hit %s\n", msg); | 78 PrintF("Simulator hit %s\n", msg); |
130 } | 79 } |
131 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); | 80 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); |
132 Debug(); | 81 Debug(); |
133 } | 82 } |
134 #endif | |
135 | |
136 | 83 |
137 int32_t ArmDebugger::GetRegisterValue(int regnum) { | 84 int32_t ArmDebugger::GetRegisterValue(int regnum) { |
138 if (regnum == kPCRegister) { | 85 if (regnum == kPCRegister) { |
139 return sim_->get_pc(); | 86 return sim_->get_pc(); |
140 } else { | 87 } else { |
141 return sim_->get_register(regnum); | 88 return sim_->get_register(regnum); |
142 } | 89 } |
143 } | 90 } |
144 | 91 |
145 | |
146 double ArmDebugger::GetRegisterPairDoubleValue(int regnum) { | 92 double ArmDebugger::GetRegisterPairDoubleValue(int regnum) { |
147 return sim_->get_double_from_register_pair(regnum); | 93 return sim_->get_double_from_register_pair(regnum); |
148 } | 94 } |
149 | 95 |
150 | 96 |
151 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) { | 97 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) { |
152 return sim_->get_double_from_d_register(regnum); | 98 return sim_->get_double_from_d_register(regnum); |
153 } | 99 } |
154 | 100 |
155 | 101 |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 inexact_vfp_flag_ = false; | 703 inexact_vfp_flag_ = false; |
758 | 704 |
759 // The sp is initialized to point to the bottom (high address) of the | 705 // The sp is initialized to point to the bottom (high address) of the |
760 // allocated stack area. To be safe in potential stack underflows we leave | 706 // allocated stack area. To be safe in potential stack underflows we leave |
761 // some buffer below. | 707 // some buffer below. |
762 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; | 708 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; |
763 // The lr and pc are initialized to a known bad value that will cause an | 709 // The lr and pc are initialized to a known bad value that will cause an |
764 // access violation if the simulator ever tries to execute it. | 710 // access violation if the simulator ever tries to execute it. |
765 registers_[pc] = bad_lr; | 711 registers_[pc] = bad_lr; |
766 registers_[lr] = bad_lr; | 712 registers_[lr] = bad_lr; |
767 InitializeCoverage(); | |
768 | 713 |
769 last_debugger_input_ = NULL; | 714 last_debugger_input_ = NULL; |
770 } | 715 } |
771 | 716 |
772 | 717 |
773 Simulator::~Simulator() { free(stack_); } | 718 Simulator::~Simulator() { free(stack_); } |
774 | 719 |
775 | 720 |
776 // When the generated code calls an external reference we need to catch that in | 721 // When the generated code calls an external reference we need to catch that in |
777 // the simulator. The external reference will be a function compiled for the | 722 // the simulator. The external reference will be a function compiled for the |
(...skipping 3531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4309 set_register(sp, current_sp + sizeof(uintptr_t)); | 4254 set_register(sp, current_sp + sizeof(uintptr_t)); |
4310 return address; | 4255 return address; |
4311 } | 4256 } |
4312 | 4257 |
4313 } // namespace internal | 4258 } // namespace internal |
4314 } // namespace v8 | 4259 } // namespace v8 |
4315 | 4260 |
4316 #endif // USE_SIMULATOR | 4261 #endif // USE_SIMULATOR |
4317 | 4262 |
4318 #endif // V8_TARGET_ARCH_ARM | 4263 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |