OLD | NEW |
1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 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 10 matching lines...) Expand all Loading... |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 | 28 |
29 #include "d8.h" | 29 #include "d8.h" |
30 #include "d8-debug.h" | 30 #include "d8-debug.h" |
| 31 #include "platform.h" |
| 32 #include "debug-agent.h" |
31 | 33 |
32 | 34 |
33 namespace v8 { | 35 namespace v8 { |
34 | 36 |
35 | 37 |
36 void HandleDebugEvent(DebugEvent event, | 38 void HandleDebugEvent(DebugEvent event, |
37 Handle<Object> exec_state, | 39 Handle<Object> exec_state, |
38 Handle<Object> event_data, | 40 Handle<Object> event_data, |
39 Handle<Value> data) { | 41 Handle<Value> data) { |
40 HandleScope scope; | 42 HandleScope scope; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 String::Utf8Value text_str(response_details->Get(String::New("text"))); | 137 String::Utf8Value text_str(response_details->Get(String::New("text"))); |
136 if (text_str.length() > 0) { | 138 if (text_str.length() > 0) { |
137 printf("%s\n", *text_str); | 139 printf("%s\n", *text_str); |
138 } | 140 } |
139 running = | 141 running = |
140 response_details->Get(String::New("running"))->ToBoolean()->Value(); | 142 response_details->Get(String::New("running"))->ToBoolean()->Value(); |
141 } | 143 } |
142 } | 144 } |
143 | 145 |
144 | 146 |
| 147 void RunRemoteDebugger(int port) { |
| 148 RemoteDebugger debugger(port); |
| 149 debugger.Run(); |
| 150 } |
| 151 |
| 152 |
| 153 void RemoteDebugger::Run() { |
| 154 bool ok; |
| 155 |
| 156 // Make sure that socket support is initialized. |
| 157 ok = i::Socket::Setup(); |
| 158 if (!ok) { |
| 159 printf("Unable to initialize socket support %d\n", i::Socket::LastError()); |
| 160 return; |
| 161 } |
| 162 |
| 163 // Connect to the debugger agent. |
| 164 conn_ = i::OS::CreateSocket(); |
| 165 static const int kPortStrSize = 6; |
| 166 char port_str[kPortStrSize]; |
| 167 i::OS::SNPrintF(i::Vector<char>(port_str, kPortStrSize), "%d", port_); |
| 168 ok = conn_->Connect("localhost", port_str); |
| 169 if (!ok) { |
| 170 printf("Unable to connect to debug agent %d\n", i::Socket::LastError()); |
| 171 return; |
| 172 } |
| 173 |
| 174 // Start the receiver thread. |
| 175 ReceiverThread receiver(this); |
| 176 receiver.Start(); |
| 177 |
| 178 // Start the keyboard thread. |
| 179 KeyboardThread keyboard(this); |
| 180 keyboard.Start(); |
| 181 |
| 182 // Process events received from debugged VM and from the keyboard. |
| 183 bool terminate = false; |
| 184 while (!terminate) { |
| 185 event_available_->Wait(); |
| 186 RemoteDebuggerEvent* event = GetEvent(); |
| 187 switch (event->type()) { |
| 188 case RemoteDebuggerEvent::kMessage: |
| 189 HandleMessageReceived(event->data()); |
| 190 break; |
| 191 case RemoteDebuggerEvent::kKeyboard: |
| 192 HandleKeyboardCommand(event->data()); |
| 193 break; |
| 194 case RemoteDebuggerEvent::kDisconnect: |
| 195 terminate = true; |
| 196 break; |
| 197 |
| 198 default: |
| 199 UNREACHABLE(); |
| 200 } |
| 201 delete event; |
| 202 } |
| 203 |
| 204 // Wait for the receiver thread to end. |
| 205 receiver.Join(); |
| 206 } |
| 207 |
| 208 |
| 209 void RemoteDebugger::MessageReceived(i::SmartPointer<char> message) { |
| 210 RemoteDebuggerEvent* event = |
| 211 new RemoteDebuggerEvent(RemoteDebuggerEvent::kMessage, message); |
| 212 AddEvent(event); |
| 213 } |
| 214 |
| 215 |
| 216 void RemoteDebugger::KeyboardCommand(i::SmartPointer<char> command) { |
| 217 RemoteDebuggerEvent* event = |
| 218 new RemoteDebuggerEvent(RemoteDebuggerEvent::kKeyboard, command); |
| 219 AddEvent(event); |
| 220 } |
| 221 |
| 222 |
| 223 void RemoteDebugger::ConnectionClosed() { |
| 224 RemoteDebuggerEvent* event = |
| 225 new RemoteDebuggerEvent(RemoteDebuggerEvent::kDisconnect, |
| 226 i::SmartPointer<char>()); |
| 227 AddEvent(event); |
| 228 } |
| 229 |
| 230 |
| 231 void RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) { |
| 232 i::ScopedLock lock(event_access_); |
| 233 if (head_ == NULL) { |
| 234 ASSERT(tail_ == NULL); |
| 235 head_ = event; |
| 236 tail_ = event; |
| 237 } else { |
| 238 ASSERT(tail_ != NULL); |
| 239 tail_->set_next(event); |
| 240 tail_ = event; |
| 241 } |
| 242 event_available_->Signal(); |
| 243 } |
| 244 |
| 245 |
| 246 RemoteDebuggerEvent* RemoteDebugger::GetEvent() { |
| 247 i::ScopedLock lock(event_access_); |
| 248 ASSERT(head_ != NULL); |
| 249 RemoteDebuggerEvent* result = head_; |
| 250 head_ = head_->next(); |
| 251 if (head_ == NULL) { |
| 252 ASSERT(tail_ == result); |
| 253 tail_ = NULL; |
| 254 } |
| 255 return result; |
| 256 } |
| 257 |
| 258 |
| 259 void RemoteDebugger::HandleMessageReceived(char* message) { |
| 260 HandleScope scope; |
| 261 |
| 262 // Print the event details. |
| 263 TryCatch try_catch; |
| 264 Handle<Object> details = |
| 265 Shell::DebugMessageDetails(Handle<String>::Cast(String::New(message))); |
| 266 if (try_catch.HasCaught()) { |
| 267 Shell::ReportException(&try_catch); |
| 268 return; |
| 269 } |
| 270 String::Utf8Value str(details->Get(String::New("text"))); |
| 271 if (str.length() == 0) { |
| 272 // Empty string is used to signal not to process this event. |
| 273 return; |
| 274 } |
| 275 if (*str != NULL) { |
| 276 printf("%s\n", *str); |
| 277 } else { |
| 278 printf("???\n"); |
| 279 } |
| 280 printf("dbg> "); |
| 281 } |
| 282 |
| 283 |
| 284 void RemoteDebugger::HandleKeyboardCommand(char* command) { |
| 285 HandleScope scope; |
| 286 |
| 287 // Convert the debugger command to a JSON debugger request. |
| 288 TryCatch try_catch; |
| 289 Handle<Value> request = |
| 290 Shell::DebugCommandToJSONRequest(String::New(command)); |
| 291 if (try_catch.HasCaught()) { |
| 292 Shell::ReportException(&try_catch); |
| 293 return; |
| 294 } |
| 295 |
| 296 // If undefined is returned the command was handled internally and there is |
| 297 // no JSON to send. |
| 298 if (request->IsUndefined()) { |
| 299 return; |
| 300 } |
| 301 |
| 302 // Send the JSON debugger request. |
| 303 i::DebuggerAgentUtil::SendMessage(conn_, Handle<String>::Cast(request)); |
| 304 } |
| 305 |
| 306 |
| 307 void ReceiverThread::Run() { |
| 308 while (true) { |
| 309 // Receive a message. |
| 310 i::SmartPointer<char> message = |
| 311 i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn()); |
| 312 if (*message == NULL) { |
| 313 remote_debugger_->ConnectionClosed(); |
| 314 return; |
| 315 } |
| 316 |
| 317 // Pass the message to the main thread. |
| 318 remote_debugger_->MessageReceived(message); |
| 319 } |
| 320 } |
| 321 |
| 322 |
| 323 void KeyboardThread::Run() { |
| 324 static const int kBufferSize = 256; |
| 325 while (true) { |
| 326 // read keyboard input. |
| 327 char command[kBufferSize]; |
| 328 char* str = fgets(command, kBufferSize, stdin); |
| 329 if (str == NULL) { |
| 330 break; |
| 331 } |
| 332 |
| 333 // Pass the keyboard command to the main thread. |
| 334 remote_debugger_->KeyboardCommand( |
| 335 i::SmartPointer<char>(i::OS::StrDup(command))); |
| 336 } |
| 337 } |
| 338 |
| 339 |
145 } // namespace v8 | 340 } // namespace v8 |
OLD | NEW |