| Index: experimental/linux_debug_server/debugger/nacl-gdb_server/debug_server.cc
|
| diff --git a/experimental/linux_debug_server/debugger/nacl-gdb_server/debug_server.cc b/experimental/linux_debug_server/debugger/nacl-gdb_server/debug_server.cc
|
| deleted file mode 100755
|
| index f2266d08b70a2a762c296ee93900687af5d585ed..0000000000000000000000000000000000000000
|
| --- a/experimental/linux_debug_server/debugger/nacl-gdb_server/debug_server.cc
|
| +++ /dev/null
|
| @@ -1,411 +0,0 @@
|
| -// Copyright (c) 2011 The Native Client 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 "debugger/nacl-gdb_server/debug_server.h"
|
| -#include <stdio.h>
|
| -#include <signal.h>
|
| -#include <algorithm>
|
| -#include "debugger/core/debuggee_thread.h"
|
| -#include "debugger/rsp/rsp_common_replies.h"
|
| -#include "debugger/rsp/rsp_control_packets.h"
|
| -#include "debugger/rsp/rsp_info_packets.h"
|
| -#include "debugger/rsp/rsp_packet_utils.h"
|
| -#include "debugger/rsp/rsp_packets.h"
|
| -#include "debugger/rsp/rsp_threads_packets.h"
|
| -#include "debugger/nacl-gdb_server/gdb_registers.h"
|
| -
|
| -namespace {
|
| -const int kReadBufferSize = 1024;
|
| -const int kVS2008_THREAD_INFO = 0x406D1388;
|
| -const int kStopTimeoutMs = 1000;
|
| -const int kMaxPacketsToReadAtOnce = 100;
|
| -
|
| -// Error codes returned to the client (debugger).
|
| -const int kErrorNoFocusedThread = 1;
|
| -const int kErrorNoFocusedProcess = 2;
|
| -const int kErrorSetFocusToAllThreadsIsNotSupported = 3;
|
| -const int kErrorReadMemoryFailed = 4;
|
| -const int kErrorPacketIsTooLarge = 5;
|
| -const int kErrorWriteMemoryFailed = 6;
|
| -const int kErrorGetThreadContextFailed = 7;
|
| -const int kErrorSetThreadContextFailed = 8;
|
| -const int kErrorSingleStepFailed = 9;
|
| -const int kErrorThreadIsDead = 10;
|
| -const int kErrorThreadNotFound = 11;
|
| -
|
| -rsp::StopReply CreateStopReplyFromDebugEvent(const debug::DebugEvent& de) {
|
| - switch (de.process_state_) {
|
| - case debug::RUNNING: return rsp::StopReply(rsp::StopReply::STILL_RUNNING);
|
| - case debug::PROCESS_STOPPED: {
|
| - rsp::StopReply msg(rsp::StopReply::SIGNALED);
|
| - msg.set_signal_number(de.signal_no_);
|
| - return msg;
|
| - }
|
| - case debug::PROCESS_TERMINATED: {
|
| - rsp::StopReply msg(rsp::StopReply::TERMINATED);
|
| - msg.set_signal_number(de.signal_no_);
|
| - return msg;
|
| - }
|
| - case debug::PROCESS_EXITED: {
|
| - rsp::StopReply msg(rsp::StopReply::EXITED);
|
| - msg.set_exit_code(de.exit_code_);
|
| - return msg;
|
| - }
|
| - }
|
| - return rsp::StopReply(rsp::StopReply::EXITED);
|
| -}
|
| -
|
| -#define AAA(x) printf("\t%s = 0x%lx\n", #x, context.x)
|
| -
|
| -void PrintContext(const user_regs_struct& context) {
|
| - printf("Context {\n");
|
| - AAA(r15);
|
| - AAA(r14);
|
| - AAA(r13);
|
| - AAA(r12);
|
| - AAA(rbp);
|
| - AAA(rbx);
|
| - AAA(r11);
|
| - AAA(r10);
|
| - AAA(r9);
|
| - AAA(r8);
|
| - AAA(rax);
|
| - AAA(rcx);
|
| - AAA(rdx);
|
| - AAA(rsi);
|
| - AAA(rdi);
|
| - AAA(rip);
|
| - AAA(cs);
|
| - AAA(eflags);
|
| - AAA(rsp);
|
| - AAA(ss);
|
| - AAA(ds);
|
| - AAA(es);
|
| - AAA(fs);
|
| - AAA(gs);
|
| - printf("}\n");
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -namespace debug {
|
| -DebugServer::DebugServer(DebugAPI* debug_api, int listen_port)
|
| - : debug_api_(debug_api),
|
| - client_connected_(false),
|
| - debuggee_process_(NULL),
|
| - focused_thread_id_(0),
|
| - listen_port_(listen_port),
|
| - continue_from_halt_(false) {
|
| -}
|
| -
|
| -DebugServer::~DebugServer() {
|
| - if (NULL != debuggee_process_) {
|
| - delete debuggee_process_;
|
| - debuggee_process_ = NULL;
|
| - }
|
| -}
|
| -
|
| -bool DebugServer::Init() {
|
| - rsp_packetizer_.SetPacketConsumer(this);
|
| - debuggee_process_ = new DebuggeeProcess(debug_api_);
|
| - if (NULL == debuggee_process_)
|
| - return false;
|
| -
|
| - return ListenForRspConnection();
|
| -}
|
| -
|
| -bool DebugServer::ListenForRspConnection() {
|
| - bool res = listening_socket_.Listen(listen_port_);
|
| - if (res)
|
| - printf("Started listening on port %d ...\n", listen_port_);
|
| - else
|
| - printf("DebugServer::ListenForRspConnection failed port=%d",
|
| - listen_port_);
|
| -
|
| - return res;
|
| -}
|
| -
|
| -void DebugServer::HandleNetwork() {
|
| - if (!client_connection_.IsConnected()) {
|
| - if (client_connected_) {
|
| - client_connected_ = false;
|
| - printf("Dropped connection from debugger.\n");
|
| - }
|
| - if (listening_socket_.Accept(20, &client_connection_)) {
|
| - client_connected_ = true;
|
| - printf("Got connection from debugger.\n");
|
| - }
|
| - } else {
|
| - char buff[kReadBufferSize];
|
| - for (int i = 0; i < kMaxPacketsToReadAtOnce; i++) {
|
| - size_t read_bytes = client_connection_.Read(buff,
|
| - sizeof(buff) - 1,
|
| - 20);
|
| - if (read_bytes > 0) {
|
| - buff[read_bytes] = 0;
|
| - printf("r>[%s]\n", buff);
|
| - rsp_packetizer_.OnData(buff, read_bytes);
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void DebugServer::HandleExecutionEngine() {
|
| - DebugEvent de;
|
| - if (debuggee_process_->WaitForDebugEventAndDispatchIt(&de)) {
|
| - // Now, we have a halted NaCl process on our hands.
|
| - if (0 == focused_thread_id_)
|
| - focused_thread_id_ = de.pid_;
|
| - if (continue_from_halt_) {
|
| - continue_from_halt_ = false;
|
| - SendRspMessageToClient(CreateStopReplyFromDebugEvent(de));
|
| - }
|
| - }
|
| -}
|
| -
|
| -void DebugServer::DoWork() {
|
| - HandleNetwork();
|
| - HandleExecutionEngine();
|
| -}
|
| -
|
| -void DebugServer::SendRspMessageToClient(const rsp::Packet& msg) {
|
| - Blob text;
|
| - msg.ToBlob(&text);
|
| - Blob wire_msg;
|
| - rsp::PacketUtils::AddEnvelope(text, &wire_msg);
|
| - client_connection_.WriteAll(wire_msg);
|
| - printf("T>[%s]\n", text.ToString().c_str());
|
| - printf("t>[%s]\n", wire_msg.ToString().c_str());
|
| -}
|
| -
|
| -DebuggeeThread* DebugServer::GetFocusedThread() {
|
| - DebuggeeThread* thread = debuggee_process_->GetThread(focused_thread_id_);
|
| - if (NULL == thread)
|
| - SendErrorReply(kErrorNoFocusedThread);
|
| - return thread;
|
| -}
|
| -
|
| -void DebugServer::OnUnknownCommand() {
|
| - // Empty RSP packet is returned for unsupported commands.
|
| - SendRspMessageToClient(rsp::EmptyPacket());
|
| -}
|
| -
|
| -void DebugServer::OnPacket(const Blob& body, bool valid_checksum) {
|
| - if (valid_checksum)
|
| - client_connection_.WriteAll("+", 1); // Send low-level RSP acknowledgment.
|
| -
|
| - Blob msg = body;
|
| - rsp::Packet* command = rsp::Packet::CreateFromBlob(&msg, NULL);
|
| - if (NULL != command) {
|
| - command->AcceptVisitor(this);
|
| - delete command;
|
| - } else {
|
| - OnUnknownCommand();
|
| - }
|
| -}
|
| -
|
| -void DebugServer::OnUnexpectedByte(uint8_t unexpected_byte) {
|
| - printf("msg='DebugServer::OnUnexpectedChar' c='0x%x'",
|
| - static_cast<int>(unexpected_byte));
|
| -}
|
| -
|
| -void DebugServer::SendErrorReply(int error) {
|
| - SendRspMessageToClient(rsp::ErrorReply(error));
|
| -}
|
| -
|
| -void DebugServer::OnBreak() {
|
| - debug_api_->PostSignal(focused_thread_id_, SIGSTOP);
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::GetStopReasonCommand* packet) {
|
| - DebuggeeThread* thread = GetFocusedThread();
|
| - if (NULL == thread)
|
| - return;
|
| - SendRspMessageToClient(CreateStopReplyFromDebugEvent(thread->last_debug_event()));
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::ContinueCommand* packet) {
|
| - DebuggeeThread* thread = GetFocusedThread();
|
| - if (NULL != thread) {
|
| - continue_from_halt_ = true;
|
| - debuggee_process_->Continue(focused_thread_id_);
|
| - }
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::QuerySupportedCommand* packet) {
|
| - rsp::QuerySupportedReply reply;
|
| - reply.AddFeature("PacketSize", "7cf");
|
| - reply.AddFeature("qXfer:libraries:read", "+");
|
| - reply.AddFeature("qXfer:features:read", "+");
|
| - SendRspMessageToClient(reply);
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::QXferFeaturesReadCommand* packet) {
|
| - // qXfer:features:read:target.xml:0,7ca
|
| - if (packet->file_name() == "target.xml") {
|
| - rsp::QXferReply reply;
|
| - reply.set_body("<target><architecture>i386:x86-64</architecture></target>");
|
| - reply.set_eom(true);
|
| - SendRspMessageToClient(reply);
|
| - } else {
|
| - OnUnknownCommand();
|
| - }
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::SetCurrentThreadCommand* packet) {
|
| - int tid = static_cast<int>(packet->thread_id());
|
| - bool res = false;
|
| - if (-1 == tid) { // all threads
|
| - res = true;
|
| - } else if (0 == tid) { // any thread
|
| - res = true;
|
| - } else {
|
| - DebuggeeThread* thread = debuggee_process_->GetThread(tid);
|
| - if (NULL != thread) {
|
| - res = true;
|
| - focused_thread_id_ = tid;
|
| - }
|
| - }
|
| - if (res)
|
| - SendRspMessageToClient(rsp::OkReply());
|
| - else
|
| - SendErrorReply(kErrorThreadNotFound);
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::ReadMemoryCommand* packet) {
|
| - size_t sz = packet->num_of_bytes();
|
| - if (0 == sz) {
|
| - SendRspMessageToClient(rsp::EmptyPacket());
|
| - return;
|
| - }
|
| - char buff[rsp::kMaxRspPacketSize / 2]; // 2 characters per byte.
|
| - if (sizeof(buff) < sz)
|
| - sz = sizeof(buff);
|
| -
|
| - DebuggeeThread* thread = GetFocusedThread();
|
| - if (NULL != thread) {
|
| - uint64_t addr = packet->addr();
|
| - // massage address to support gdb
|
| - if (addr < debuggee_process_->nexe_mem_base())
|
| - addr += debuggee_process_->nexe_mem_base();
|
| -
|
| - size_t rd = 0;
|
| - if (debug_api_->ReadMemory(focused_thread_id_, addr, buff, sz, &rd)) {
|
| - rsp::BlobReply reply;
|
| - reply.set_data(buff, sz);
|
| - SendRspMessageToClient(reply);
|
| - } else {
|
| - SendErrorReply(kErrorReadMemoryFailed);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::WriteMemoryCommand* packet) {
|
| - const debug::Blob& data = packet->data();
|
| - DebuggeeThread* thread = GetFocusedThread();
|
| - if (NULL != thread) {
|
| - char tmp[rsp::kMaxRspPacketSize];
|
| - if (data.size() > sizeof(tmp)) {
|
| - SendErrorReply(kErrorPacketIsTooLarge);
|
| - return;
|
| - }
|
| - data.Peek(0, tmp, data.size());
|
| - uint64_t addr = packet->addr();
|
| - // massage address to support gdb
|
| - if (addr < debuggee_process_->nexe_mem_base())
|
| - addr += debuggee_process_->nexe_mem_base();
|
| -
|
| - size_t wr = 0;
|
| - bool res = debug_api_->WriteMemory(focused_thread_id_, addr, tmp, data.size(), &wr);
|
| - if (res)
|
| - SendRspMessageToClient(rsp::OkReply());
|
| - else
|
| - SendErrorReply(kErrorWriteMemoryFailed);
|
| - }
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::ReadRegistersCommand* packet) {
|
| - DebuggeeThread* thread = GetFocusedThread();
|
| - if (NULL != thread) {
|
| - user_regs_struct context;
|
| - if (!debug_api_->ReadThreadContext(thread->id(), &context)) {
|
| - SendErrorReply(kErrorGetThreadContextFailed);
|
| - } else {
|
| - PrintContext(context);
|
| - Blob blob;
|
| - rsp::CONTEXTToGdbRegisters(context, &blob);
|
| - rsp::BlobReply reply;
|
| - reply.set_data(blob);
|
| - SendRspMessageToClient(reply);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::WriteRegistersCommand* packet) {
|
| - DebuggeeThread* thread = GetFocusedThread();
|
| - if (NULL != thread) {
|
| - user_regs_struct context;
|
| - if (!debug_api_->ReadThreadContext(thread->id(), &context)) {
|
| - SendErrorReply(kErrorGetThreadContextFailed);
|
| - return;
|
| - }
|
| - rsp::GdbRegistersToCONTEXT(packet->data(), &context);
|
| - if (!debug_api_->WriteThreadContext(thread->id(), &context))
|
| - SendErrorReply(kErrorSetThreadContextFailed);
|
| - else
|
| - SendRspMessageToClient(rsp::OkReply());
|
| - }
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::GetCurrentThreadCommand* packet) {
|
| - rsp::GetCurrentThreadReply reply;
|
| - reply.set_value(focused_thread_id_);
|
| - SendRspMessageToClient(reply);
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::StepCommand* packet) {
|
| - DebuggeeThread* thread = GetFocusedThread();
|
| - if (NULL != thread) {
|
| - if (!debug_api_->SingleStep(focused_thread_id_)) {
|
| - SendErrorReply(kErrorSingleStepFailed);
|
| - } else {
|
| - thread->Continue();
|
| - continue_from_halt_ = true;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::IsThreadAliveCommand* packet) {
|
| - if (NULL != debuggee_process_->GetThread(packet->value()))
|
| - SendRspMessageToClient(rsp::OkReply());
|
| - else
|
| - SendErrorReply(kErrorThreadNotFound);
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::GetThreadInfoCommand* packet) {
|
| - rsp::GetThreadInfoReply reply;
|
| - if (packet->get_more()) {
|
| - // TODO(garianov): add support for multi-packet replies.
|
| - reply.set_eom(true);
|
| - } else {
|
| - std::deque<int> tids;
|
| - debuggee_process_->GetThreadsIds(&tids);
|
| - reply.set_threads_ids(tids);
|
| - reply.set_eom(false);
|
| - }
|
| - SendRspMessageToClient(reply);
|
| -}
|
| -
|
| -void DebugServer::Visit(rsp::GetOffsetsCommand* packet) {
|
| - uint64_t mb = debuggee_process_->nexe_mem_base();
|
| - rsp::GetOffsetsReply reply;
|
| - reply.set_data_offset(mb);
|
| - reply.set_text_offset(mb);
|
| -
|
| - SendRspMessageToClient(reply);
|
| -}
|
| -
|
| -} // namespace debug
|
| -
|
|
|