// Copyright 2008 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef V8_D8_DEBUG_H_ #define V8_D8_DEBUG_H_ #include "d8.h" #include "debug.h" namespace v8 { void HandleDebugEvent(DebugEvent event, Handle<Object> exec_state, Handle<Object> event_data, Handle<Value> data); // Start the remove debugger connecting to a V8 debugger agent on the specified // port. void RunRemoteDebugger(int port); // Forward declerations. class RemoteDebuggerEvent; class ReceiverThread; // Remote debugging class. class RemoteDebugger { public: explicit RemoteDebugger(int port) : port_(port), event_access_(i::OS::CreateMutex()), event_available_(i::OS::CreateSemaphore(0)), head_(NULL), tail_(NULL) {} void Run(); // Handle events from the subordinate threads. void MessageReceived(i::SmartArrayPointer<char> message); void KeyboardCommand(i::SmartArrayPointer<char> command); void ConnectionClosed(); private: // Add new debugger event to the list. void AddEvent(RemoteDebuggerEvent* event); // Read next debugger event from the list. RemoteDebuggerEvent* GetEvent(); // Handle a message from the debugged V8. void HandleMessageReceived(char* message); // Handle a keyboard command. void HandleKeyboardCommand(char* command); // Get connection to agent in debugged V8. i::Socket* conn() { return conn_; } int port_; // Port used to connect to debugger V8. i::Socket* conn_; // Connection to debugger agent in debugged V8. // Linked list of events from debugged V8 and from keyboard input. Access to // the list is guarded by a mutex and a semaphore signals new items in the // list. i::Mutex* event_access_; i::Semaphore* event_available_; RemoteDebuggerEvent* head_; RemoteDebuggerEvent* tail_; friend class ReceiverThread; }; // Thread reading from debugged V8 instance. class ReceiverThread: public i::Thread { public: explicit ReceiverThread(RemoteDebugger* remote_debugger) : Thread("d8:ReceiverThrd"), remote_debugger_(remote_debugger) {} ~ReceiverThread() {} void Run(); private: RemoteDebugger* remote_debugger_; }; // Thread reading keyboard input. class KeyboardThread: public i::Thread { public: explicit KeyboardThread(RemoteDebugger* remote_debugger) : Thread("d8:KeyboardThrd"), remote_debugger_(remote_debugger) {} ~KeyboardThread() {} void Run(); private: RemoteDebugger* remote_debugger_; }; // Events processed by the main deubgger thread. class RemoteDebuggerEvent { public: RemoteDebuggerEvent(int type, i::SmartArrayPointer<char> data) : type_(type), data_(data), next_(NULL) { ASSERT(type == kMessage || type == kKeyboard || type == kDisconnect); } static const int kMessage = 1; static const int kKeyboard = 2; static const int kDisconnect = 3; int type() { return type_; } char* data() { return *data_; } private: void set_next(RemoteDebuggerEvent* event) { next_ = event; } RemoteDebuggerEvent* next() { return next_; } int type_; i::SmartArrayPointer<char> data_; RemoteDebuggerEvent* next_; friend class RemoteDebugger; }; } // namespace v8 #endif // V8_D8_DEBUG_H_