1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2008 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "d8.h" 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "d8-debug.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug-agent.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockstatic bool was_running = true; 389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid PrintPrompt(bool is_running) { 409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const char* prompt = is_running? "> " : "dbg> "; 419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block was_running = is_running; 429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block printf("%s", prompt); 436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block fflush(stdout); 446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid PrintPrompt() { 489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block PrintPrompt(was_running); 499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid HandleDebugEvent(DebugEvent event, 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> exec_state, 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> event_data, 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Value> data) { 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleScope scope; 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for handled event. 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (event != Break && event != Exception && event != AfterCompile) { 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TryCatch try_catch; 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the toJSONProtocol function on the event and get the JSON format. 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Local<String> to_json_fun_name = String::New("toJSONProtocol"); 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Local<Function> to_json_fun = 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Function::Cast(*event_data->Get(to_json_fun_name)); 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Local<Value> event_json = to_json_fun->Call(event_data, 0, NULL); 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_catch.HasCaught()) { 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Shell::ReportException(&try_catch); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print the event details. 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> details = 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Shell::DebugMessageDetails(Handle<String>::Cast(event_json)); 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_catch.HasCaught()) { 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Shell::ReportException(&try_catch); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String::Utf8Value str(details->Get(String::New("text"))); 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (str.length() == 0) { 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Empty string is used to signal not to process this event. 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("%s\n", *str); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the debug command processor. 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Local<String> fun_name = String::New("debugCommandProcessor"); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Local<Function> fun = Function::Cast(*exec_state->Get(fun_name)); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Local<Object> cmd_processor = 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object::Cast(*fun->Call(exec_state, 0, NULL)); 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_catch.HasCaught()) { 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Shell::ReportException(&try_catch); 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kBufferSize = 256; 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool running = false; 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (!running) { 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char command[kBufferSize]; 1039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block PrintPrompt(running); 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* str = fgets(command, kBufferSize, stdin); 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (str == NULL) break; 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ignore empty commands. 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (strlen(command) == 0) continue; 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TryCatch try_catch; 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the debugger command to a JSON debugger request. 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Value> request = 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Shell::DebugCommandToJSONRequest(String::New(command)); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_catch.HasCaught()) { 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Shell::ReportException(&try_catch); 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block continue; 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If undefined is returned the command was handled internally and there is 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // no JSON to send. 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (request->IsUndefined()) { 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block continue; 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<String> fun_name; 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Function> fun; 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All the functions used below take one argument. 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kArgc = 1; 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Value> args[kArgc]; 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the JavaScript to convert the debug command line to a JSON 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // request, invoke the JSON request and convert the JSON respose to a text 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // representation. 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fun_name = String::New("processDebugRequest"); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fun = Handle<Function>::Cast(cmd_processor->Get(fun_name)); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block args[0] = request; 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Value> response_val = fun->Call(cmd_processor, kArgc, args); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_catch.HasCaught()) { 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Shell::ReportException(&try_catch); 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block continue; 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<String> response = Handle<String>::Cast(response_val); 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the debugger response into text details and the running state. 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> response_details = Shell::DebugMessageDetails(response); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_catch.HasCaught()) { 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Shell::ReportException(&try_catch); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block continue; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String::Utf8Value text_str(response_details->Get(String::New("text"))); 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (text_str.length() > 0) { 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("%s\n", *text_str); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block running = 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block response_details->Get(String::New("running"))->ToBoolean()->Value(); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RunRemoteDebugger(int port) { 16244f0eee88ff00398ff7f715fab053374d808c90dSteve Block RemoteDebugger debugger(i::Isolate::Current(), port); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block debugger.Run(); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::Run() { 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool ok; 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that socket support is initialized. 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ok = i::Socket::Setup(); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!ok) { 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("Unable to initialize socket support %d\n", i::Socket::LastError()); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Connect to the debugger agent. 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block conn_ = i::OS::CreateSocket(); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kPortStrSize = 6; 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char port_str[kPortStrSize]; 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::OS::SNPrintF(i::Vector<char>(port_str, kPortStrSize), "%d", port_); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ok = conn_->Connect("localhost", port_str); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!ok) { 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("Unable to connect to debug agent %d\n", i::Socket::LastError()); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Start the receiver thread. 18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ReceiverThread receiver(isolate_, this); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block receiver.Start(); 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Start the keyboard thread. 19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block KeyboardThread keyboard(isolate_, this); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block keyboard.Start(); 1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block PrintPrompt(); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Process events received from debugged VM and from the keyboard. 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool terminate = false; 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (!terminate) { 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block event_available_->Wait(); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RemoteDebuggerEvent* event = GetEvent(); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (event->type()) { 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RemoteDebuggerEvent::kMessage: 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleMessageReceived(event->data()); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RemoteDebuggerEvent::kKeyboard: 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleKeyboardCommand(event->data()); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case RemoteDebuggerEvent::kDisconnect: 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block terminate = true; 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete event; 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Wait for the receiver thread to end. 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block receiver.Join(); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::MessageReceived(i::SmartPointer<char> message) { 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RemoteDebuggerEvent* event = 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new RemoteDebuggerEvent(RemoteDebuggerEvent::kMessage, message); 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddEvent(event); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::KeyboardCommand(i::SmartPointer<char> command) { 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RemoteDebuggerEvent* event = 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new RemoteDebuggerEvent(RemoteDebuggerEvent::kKeyboard, command); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddEvent(event); 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::ConnectionClosed() { 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RemoteDebuggerEvent* event = 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new RemoteDebuggerEvent(RemoteDebuggerEvent::kDisconnect, 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::SmartPointer<char>()); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddEvent(event); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) { 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ScopedLock lock(event_access_); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (head_ == NULL) { 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(tail_ == NULL); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block head_ = event; 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tail_ = event; 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(tail_ != NULL); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tail_->set_next(event); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tail_ = event; 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block event_available_->Signal(); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRemoteDebuggerEvent* RemoteDebugger::GetEvent() { 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ScopedLock lock(event_access_); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(head_ != NULL); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RemoteDebuggerEvent* result = head_; 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block head_ = head_->next(); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (head_ == NULL) { 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(tail_ == result); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tail_ = NULL; 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::HandleMessageReceived(char* message) { 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleScope scope; 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Print the event details. 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TryCatch try_catch; 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> details = 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Shell::DebugMessageDetails(Handle<String>::Cast(String::New(message))); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_catch.HasCaught()) { 2826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Shell::ReportException(&try_catch); 2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block PrintPrompt(); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block String::Utf8Value str(details->Get(String::New("text"))); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (str.length() == 0) { 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Empty string is used to signal not to process this event. 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*str != NULL) { 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("%s\n", *str); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block printf("???\n"); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 2979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block bool is_running = details->Get(String::New("running"))->ToBoolean()->Value(); 2989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block PrintPrompt(is_running); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::HandleKeyboardCommand(char* command) { 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleScope scope; 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the debugger command to a JSON debugger request. 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TryCatch try_catch; 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Value> request = 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Shell::DebugCommandToJSONRequest(String::New(command)); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (try_catch.HasCaught()) { 3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::String::Utf8Value exception(try_catch.Exception()); 3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const char* exception_string = Shell::ToCString(exception); 3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block printf("%s\n", exception_string); 3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block PrintPrompt(); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If undefined is returned the command was handled internally and there is 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // no JSON to send. 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (request->IsUndefined()) { 3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block PrintPrompt(); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Send the JSON debugger request. 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::DebuggerAgentUtil::SendMessage(conn_, Handle<String>::Cast(request)); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ReceiverThread::Run() { 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Receive the connect message (with empty body). 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::SmartPointer<char> message = 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn()); 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(*message == NULL); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Receive a message. 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::SmartPointer<char> message = 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn()); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*message == NULL) { 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block remote_debugger_->ConnectionClosed(); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the message to the main thread. 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block remote_debugger_->MessageReceived(message); 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyboardThread::Run() { 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kBufferSize = 256; 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // read keyboard input. 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char command[kBufferSize]; 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* str = fgets(command, kBufferSize, stdin); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (str == NULL) { 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pass the keyboard command to the main thread. 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block remote_debugger_->KeyboardCommand( 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::SmartPointer<char>(i::StrDup(command))); 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace v8 368