| // Copyright 2018 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include <lib/zx/socket.h> | |
| #include <stdio.h> | |
| #include <memory> | |
| #include <thread> | |
| #include "src/developer/debug/debug_agent/debug_agent.h" | |
| #include "src/developer/debug/debug_agent/remote_api_adapter.h" | |
| #include "src/developer/debug/shared/buffered_zx_socket.h" | |
| #include "src/developer/debug/shared/message_loop_zircon.h" | |
| #include "src/developer/debug/zxdb/client/session.h" | |
| #include "src/developer/debug/zxdb/console/console.h" | |
| namespace { | |
| // Background thread function that runs the in-process debug agent. The loop | |
| // must outlive this thread. | |
| void AgentThread(debug_ipc::MessageLoopZircon* loop, zx::socket socket) { | |
| // Bind the message loop to this thread. | |
| loop->Init(); | |
| // This scope forces all the objects to be destroyed before the Cleanup() | |
| // call which will mark the message loop as not-current. | |
| { | |
| debug_ipc::BufferedZxSocket router_buffer; | |
| if (!router_buffer.Init(std::move(socket))) { | |
| fprintf(stderr, "Can't hook up stream."); | |
| return; | |
| } | |
| // Route data from the router_buffer -> RemoteAPIAdapter -> DebugAgent. | |
| debug_agent::DebugAgent agent(&router_buffer.stream()); | |
| debug_agent::RemoteAPIAdapter adapter(&agent, &router_buffer.stream()); | |
| router_buffer.set_data_available_callback([&adapter]() { adapter.OnStreamReadable(); }); | |
| loop->Run(); | |
| } | |
| loop->Cleanup(); | |
| } | |
| } // namespace | |
| // Main function for the debugger run on Zircon. This currently runs the | |
| // debug_agent in-process to avoid IPC. | |
| int main(int argc, char* argv[]) { | |
| // Create a socket to talk to the in-process debug agent. Talking sockets to | |
| // ourselves keeps the same codepath regardless of whether the debug_agent | |
| // code is running in process or remotely. | |
| zx::socket client_socket, agent_socket; | |
| if (zx::socket::create(ZX_SOCKET_STREAM, &client_socket, &agent_socket) != ZX_OK) { | |
| fprintf(stderr, "Can't create socket, aborting.\n"); | |
| return 1; | |
| } | |
| // Start background thread to run the agent in-process. | |
| debug_ipc::MessageLoopZircon agent_loop; | |
| std::thread agent_thread(&AgentThread, &agent_loop, std::move(agent_socket)); | |
| // Client message loop. | |
| debug_ipc::MessageLoopZircon client_loop; | |
| client_loop.Init(); | |
| // This scope forces all the objects to be destroyed before the Cleanup() | |
| // call which will mark the message loop as not-current. | |
| { | |
| debug_ipc::BufferedZxSocket buffer; | |
| if (!buffer.Init(std::move(client_socket))) { | |
| fprintf(stderr, "Can't hook up stream."); | |
| return 1; | |
| } | |
| // Route data from buffer -> session. | |
| zxdb::Session session(&buffer.stream()); | |
| buffer.set_data_available_callback([&session]() { session.OnStreamReadable(); }); | |
| zxdb::Console console(&session); | |
| console.Init(); | |
| client_loop.Run(); | |
| } | |
| client_loop.Cleanup(); | |
| // Ask the background thread to stop and join. | |
| agent_loop.PostTask([]() { debug_ipc::MessageLoop::Current()->QuitNow(); }); | |
| agent_thread.join(); | |
| return 0; | |
| } |