| Index: src/d8-debug.cc
|
| ===================================================================
|
| --- src/d8-debug.cc (revision 1405)
|
| +++ src/d8-debug.cc (working copy)
|
| @@ -28,6 +28,8 @@
|
|
|
| #include "d8.h"
|
| #include "d8-debug.h"
|
| +#include "platform.h"
|
| +#include "debug-agent.h"
|
|
|
|
|
| namespace v8 {
|
| @@ -142,4 +144,197 @@
|
| }
|
|
|
|
|
| +void RunRemoteDebugger(int port) {
|
| + RemoteDebugger debugger(port);
|
| + debugger.Run();
|
| +}
|
| +
|
| +
|
| +void RemoteDebugger::Run() {
|
| + bool ok;
|
| +
|
| + // Make sure that socket support is initialized.
|
| + ok = i::Socket::Setup();
|
| + if (!ok) {
|
| + printf("Unable to initialize socket support %d\n", i::Socket::LastError());
|
| + return;
|
| + }
|
| +
|
| + // Connect to the debugger agent.
|
| + conn_ = i::OS::CreateSocket();
|
| + static const int kPortStrSize = 6;
|
| + char port_str[kPortStrSize];
|
| + i::OS::SNPrintF(i::Vector<char>(port_str, kPortStrSize), "%d", port_);
|
| + ok = conn_->Connect("localhost", port_str);
|
| + if (!ok) {
|
| + printf("Unable to connect to debug agent %d\n", i::Socket::LastError());
|
| + return;
|
| + }
|
| +
|
| + // Start the receiver thread.
|
| + ReceiverThread receiver(this);
|
| + receiver.Start();
|
| +
|
| + // Start the keyboard thread.
|
| + KeyboardThread keyboard(this);
|
| + keyboard.Start();
|
| +
|
| + // Process events received from debugged VM and from the keyboard.
|
| + bool terminate = false;
|
| + while (!terminate) {
|
| + event_available_->Wait();
|
| + RemoteDebuggerEvent* event = GetEvent();
|
| + switch (event->type()) {
|
| + case RemoteDebuggerEvent::kMessage:
|
| + HandleMessageReceived(event->data());
|
| + break;
|
| + case RemoteDebuggerEvent::kKeyboard:
|
| + HandleKeyboardCommand(event->data());
|
| + break;
|
| + case RemoteDebuggerEvent::kDisconnect:
|
| + terminate = true;
|
| + break;
|
| +
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + delete event;
|
| + }
|
| +
|
| + // Wait for the receiver thread to end.
|
| + receiver.Join();
|
| +}
|
| +
|
| +
|
| +void RemoteDebugger::MessageReceived(i::SmartPointer<char> message) {
|
| + RemoteDebuggerEvent* event =
|
| + new RemoteDebuggerEvent(RemoteDebuggerEvent::kMessage, message);
|
| + AddEvent(event);
|
| +}
|
| +
|
| +
|
| +void RemoteDebugger::KeyboardCommand(i::SmartPointer<char> command) {
|
| + RemoteDebuggerEvent* event =
|
| + new RemoteDebuggerEvent(RemoteDebuggerEvent::kKeyboard, command);
|
| + AddEvent(event);
|
| +}
|
| +
|
| +
|
| +void RemoteDebugger::ConnectionClosed() {
|
| + RemoteDebuggerEvent* event =
|
| + new RemoteDebuggerEvent(RemoteDebuggerEvent::kDisconnect,
|
| + i::SmartPointer<char>());
|
| + AddEvent(event);
|
| +}
|
| +
|
| +
|
| +void RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) {
|
| + i::ScopedLock lock(event_access_);
|
| + if (head_ == NULL) {
|
| + ASSERT(tail_ == NULL);
|
| + head_ = event;
|
| + tail_ = event;
|
| + } else {
|
| + ASSERT(tail_ != NULL);
|
| + tail_->set_next(event);
|
| + tail_ = event;
|
| + }
|
| + event_available_->Signal();
|
| +}
|
| +
|
| +
|
| +RemoteDebuggerEvent* RemoteDebugger::GetEvent() {
|
| + i::ScopedLock lock(event_access_);
|
| + ASSERT(head_ != NULL);
|
| + RemoteDebuggerEvent* result = head_;
|
| + head_ = head_->next();
|
| + if (head_ == NULL) {
|
| + ASSERT(tail_ == result);
|
| + tail_ = NULL;
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +
|
| +void RemoteDebugger::HandleMessageReceived(char* message) {
|
| + HandleScope scope;
|
| +
|
| + // Print the event details.
|
| + TryCatch try_catch;
|
| + Handle<Object> details =
|
| + Shell::DebugMessageDetails(Handle<String>::Cast(String::New(message)));
|
| + if (try_catch.HasCaught()) {
|
| + Shell::ReportException(&try_catch);
|
| + return;
|
| + }
|
| + String::Utf8Value str(details->Get(String::New("text")));
|
| + if (str.length() == 0) {
|
| + // Empty string is used to signal not to process this event.
|
| + return;
|
| + }
|
| + if (*str != NULL) {
|
| + printf("%s\n", *str);
|
| + } else {
|
| + printf("???\n");
|
| + }
|
| + printf("dbg> ");
|
| +}
|
| +
|
| +
|
| +void RemoteDebugger::HandleKeyboardCommand(char* command) {
|
| + HandleScope scope;
|
| +
|
| + // Convert the debugger command to a JSON debugger request.
|
| + TryCatch try_catch;
|
| + Handle<Value> request =
|
| + Shell::DebugCommandToJSONRequest(String::New(command));
|
| + if (try_catch.HasCaught()) {
|
| + Shell::ReportException(&try_catch);
|
| + return;
|
| + }
|
| +
|
| + // If undefined is returned the command was handled internally and there is
|
| + // no JSON to send.
|
| + if (request->IsUndefined()) {
|
| + return;
|
| + }
|
| +
|
| + // Send the JSON debugger request.
|
| + i::DebuggerAgentUtil::SendMessage(conn_, Handle<String>::Cast(request));
|
| +}
|
| +
|
| +
|
| +void ReceiverThread::Run() {
|
| + while (true) {
|
| + // Receive a message.
|
| + i::SmartPointer<char> message =
|
| + i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
|
| + if (*message == NULL) {
|
| + remote_debugger_->ConnectionClosed();
|
| + return;
|
| + }
|
| +
|
| + // Pass the message to the main thread.
|
| + remote_debugger_->MessageReceived(message);
|
| + }
|
| +}
|
| +
|
| +
|
| +void KeyboardThread::Run() {
|
| + static const int kBufferSize = 256;
|
| + while (true) {
|
| + // read keyboard input.
|
| + char command[kBufferSize];
|
| + char* str = fgets(command, kBufferSize, stdin);
|
| + if (str == NULL) {
|
| + break;
|
| + }
|
| +
|
| + // Pass the keyboard command to the main thread.
|
| + remote_debugger_->KeyboardCommand(
|
| + i::SmartPointer<char>(i::OS::StrDup(command)));
|
| + }
|
| +}
|
| +
|
| +
|
| } // namespace v8
|
|
|