Index: experimental/linux_debug_server/debugger/core/debug_api.cc |
diff --git a/experimental/linux_debug_server/debugger/core/debug_api.cc b/experimental/linux_debug_server/debugger/core/debug_api.cc |
deleted file mode 100755 |
index 639a7c4fd46cd56d47e8309ea65abce62befc188..0000000000000000000000000000000000000000 |
--- a/experimental/linux_debug_server/debugger/core/debug_api.cc |
+++ /dev/null |
@@ -1,341 +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/core/debug_api.h" |
- |
-#include <errno.h> |
-#include <memory.h> |
-#include <signal.h> |
-#include <stdio.h> |
-#include <stdlib.h> |
-#include <sys/syscall.h> |
-#include <sys/types.h> |
-#include <sys/user.h> |
-#include <sys/wait.h> |
-#include <unistd.h> |
- |
-#include <deque> |
-#include <string> |
- |
-typedef int64_t ptrace_result_t; |
- |
-void Split(const char* str_in, |
- const char* delimiters, |
- std::deque<std::string>* out) { |
- char c = 0; |
- std::string str; |
- while (0 != (c = *str_in++)) { |
- if (strchr(delimiters, c)) { |
- if (str.size()) { |
- out->push_back(str); |
- str.clear(); |
- } |
- } else if ((c != '\r') && (c != '\n')) { |
- str.push_back(c); |
- } |
- } |
- if (str.size()) |
- out->push_back(str); |
-} |
- |
-std::string GetAppPathOutOfCmdLine(const char* cmd_line) { |
- std::deque<std::string> words; |
- Split(cmd_line, " \t", &words); |
- if (words.size() > 0) |
- return words[0]; |
- return cmd_line; |
-} |
- |
-std::string GetAppNameOutOfCmdLine(const char* cmd_line) { |
- std::string path = GetAppPathOutOfCmdLine(cmd_line); |
- std::deque<std::string> words; |
- Split(path.c_str(), "/", &words); |
- if (words.size() > 0) |
- return words[words.size() - 1]; |
- return cmd_line; |
-} |
- |
-namespace { |
-const int kMaxOutputDebugStringSize = 256; |
-const char kNexePrefix[] = "{7AA7C9CF-89EC-4ed3-8DAD-6DC84302AB11}"; |
-} // namespace |
- |
-namespace debug { |
-bool DebugAPI::PostSignal(pid_t pid, int signo) { |
- return (0 == kill(pid, signo)); |
-} |
- |
-bool DebugAPI::ReadDebugString(const DebugEvent& de, std::string* string) { |
- if ((SIGTRAP != de.signal_no_) || (PROCESS_STOPPED != de.process_state_)) |
- return false; |
- |
- user_regs_struct context; |
- if (!ReadThreadContext(de.pid_, &context)) |
- return false; |
- |
- uint64_t addr = context.rax; |
- char buff[kMaxOutputDebugStringSize]; |
- size_t rd = 0; |
- ReadMemory(de.pid_, addr, buff, sizeof(buff) - 1, &rd); |
- if (rd < sizeof(kNexePrefix)) |
- return false; |
- if (strncmp(buff, kNexePrefix, sizeof(kNexePrefix) - 1) != 0) |
- return false; |
- |
- buff[sizeof(buff) - 1] = 0; |
- *string = &buff[sizeof(kNexePrefix) - 1]; |
- printf("DebugString-[%s]\n", string->c_str()); |
- return true; |
-} |
- |
-bool DebugAPI::ContinueDebugEvent(pid_t pid, int signo) { |
- ptrace_result_t res = ptrace(PTRACE_CONT, pid, 0, reinterpret_cast<void*>(signo)); |
- return (0 == res); |
-} |
- |
-bool DebugAPI::StartProcess(const char* cmd_line, |
- bool trace, |
- pid_t* child_pid_out) { |
- std::string path = GetAppPathOutOfCmdLine(cmd_line); |
- std::string app_name = GetAppNameOutOfCmdLine(cmd_line); |
- |
- pid_t child_pid = fork(); |
- printf("fork -> %d\n", child_pid); |
- if (-1 == child_pid) |
- return false; |
- |
- if (0 == child_pid) { |
- // in child |
- if (trace) |
- ptrace(PTRACE_TRACEME, 0, NULL, NULL); |
- int res = execl(path.c_str(), app_name.c_str(), "", NULL); |
- |
- // TODO(garianov): how to communicate failure of execl to the debugger |
- // process? |
- // My guess is parent proc/debugger will get SIGTERM signal or TERM debug event... |
- printf("in child: execl -> %d errno=%d\n", res, errno); |
- exit(13); |
- } else { |
- // in parent |
- if (NULL != child_pid_out) |
- *child_pid_out = child_pid; |
- } |
- return true; |
-} |
- |
-bool DebugAPI::SetupProc(pid_t pid) { |
- intptr_t mask = |
- PTRACE_O_TRACEFORK | |
- PTRACE_O_TRACEVFORK | |
- PTRACE_O_TRACECLONE ; |
- void* data = reinterpret_cast<void*>(mask); |
- ptrace_result_t res = ptrace(PTRACE_SETOPTIONS, pid, 0, data); |
- if (0 != res) { |
- printf("Error: ptrace(PTRACE_SETOPTIONS(pid=%d) -> %s\n", pid, strerror(errno)); |
- } |
- return (0 != res); |
-} |
- |
-bool DebugAPI::DebugBreak(pid_t pid) { |
- return PostSignal(pid, SIGSTOP); |
-} |
- |
-bool DebugAPI::SingleStep(pid_t pid) { |
- ptrace_result_t res = ptrace(PTRACE_SINGLESTEP, pid, 0, 0); |
- return (0 == res); |
-} |
- |
- |
-bool DebugAPI::WriteMemory(pid_t pid, |
- uint64_t addr, |
- void* src, |
- size_t size, |
- size_t* written_bytes_out) { |
- size_t written_bytes = 0; |
- size_t left_bytes = size; |
- ptrace_result_t res = 0; |
- const size_t bundle_sz = sizeof(res); |
- unsigned char* ptr_src = reinterpret_cast<unsigned char*>(src); |
- unsigned char* ptr_addr = reinterpret_cast<unsigned char*>(addr); |
- |
- // Read first few bytes that rea not aligned on 4 (or 8 on 64-bit) |
- // bytes, if any. |
- uint64_t offset = addr; |
- size_t offset_from_4bytes = offset % bundle_sz; |
- if (0 != offset_from_4bytes) { |
-// printf("offset_from_4bytes = %d\n", (int)offset_from_4bytes); |
- unsigned char* beg_addr = |
- reinterpret_cast<unsigned char*>(offset - offset_from_4bytes); |
- res = ptrace(PTRACE_PEEKDATA, pid, beg_addr, 0); |
-// printf("ptrace(PTRACE_PEEKDATA(%p) -> 0x%lX\n", beg_addr, res); |
- if (0 != errno) { |
-// printf("%d ptrace -> %d\n", __LINE__, errno); |
- return false; |
- } |
- unsigned char* p = |
- reinterpret_cast<unsigned char*>(&res) + offset_from_4bytes; |
- written_bytes = bundle_sz - offset_from_4bytes; |
- if (written_bytes > size) |
- written_bytes = size; |
- |
- memcpy(p, ptr_src, written_bytes); |
- ptrace_result_t res2 = ptrace(PTRACE_POKEDATA, pid, beg_addr, reinterpret_cast<void*>(res)); |
-// printf("ptrace(PTRACE_POKEDATA(%p, 0x%lX) -> 0x%lX\n", |
-// beg_addr, |
-// res, |
-// res2); |
- if (0 != res2) { |
-// printf("%d ptrace(PTRACE_POKEDATA) -> %d\n", errno, __LINE__); |
- return false; |
- } |
- |
- ptr_src += written_bytes; |
- ptr_addr += written_bytes; |
- left_bytes -= written_bytes; |
- } |
- |
- while (left_bytes) { |
- size_t wr_bytes = bundle_sz; |
- if (wr_bytes > left_bytes) |
- wr_bytes = left_bytes; |
- |
- ptrace_result_t data = 0; |
- if (left_bytes < bundle_sz) { |
- data = ptrace(PTRACE_PEEKDATA, pid, ptr_addr, 0); |
- if (0 != errno) { |
-// printf("%d ptrace(PTRACE_PEEKDATA) -> 0x%lX\n", __LINE__, data); |
- return false; |
- } |
-// printf("ptrace(PTRACE_PEEKDATA(%p) -> 0x%lX\n", ptr_addr, data); |
- } |
- memcpy(&data, ptr_src, wr_bytes); |
-// printf("memcpy... %X\n", (unsigned int)(*ptr_src)); |
-// printf("PTRACE_POKEDATA(%p) %lX\n", ptr_addr, data); |
- |
- ptrace_result_t res = ptrace(PTRACE_POKEDATA, pid, ptr_addr, reinterpret_cast<void*>(data)); |
- if (0 != res) { |
- return false; |
- } |
- |
- written_bytes += wr_bytes; |
- ptr_src += written_bytes; |
- ptr_addr += written_bytes; |
- left_bytes -= wr_bytes; |
- } |
- |
- if (NULL != written_bytes_out) |
- *written_bytes_out = written_bytes; |
- return (size == written_bytes); |
-} |
- |
-bool DebugAPI::ReadMemory(pid_t pid, |
- uint64_t addr, |
- void* dest, |
- size_t size, |
- size_t* readed_bytes_out) { |
- size_t readed_bytes = 0; |
- size_t left_bytes = size; |
- ptrace_result_t res = 0; |
- const size_t bundle_sz = sizeof(res); |
- char* ptr_dest = reinterpret_cast<char*>(dest); |
- char* ptr_addr = reinterpret_cast<char*>(addr); |
-//printf("DebugApi::ReadProcessMemory(%d, %p, %d)\n", pid, addr, (int)size); |
-//printf("left_bytes = %d\n", (int)left_bytes); |
- |
- // Read first few bytes that rea not aligned on 4 (or 8 on 64-bit) |
- // bytes, if any. |
- uint64_t offset = addr; |
- size_t offset_from_4bytes = offset % bundle_sz; |
-//printf("===>>>>> offset_from_4bytes=%ld\n", offset_from_4bytes); |
- fflush(stdout); |
- if (0 != offset_from_4bytes) { |
- char* beg_addr = reinterpret_cast<char*>(offset - offset_from_4bytes); |
- res = ptrace(PTRACE_PEEKDATA, pid, beg_addr, 0); |
-//printf("ptrace(PTRACE_PEEKDATA(%p) -> 0x%lX\n", beg_addr, res); |
- if (0 != errno) { |
-//printf("ptrace -> %d\n", errno); |
-//printf("Errno: %s\n", strerror(errno)); |
- return false; |
- } |
- char* src = reinterpret_cast<char*>(&res) + offset_from_4bytes; |
- readed_bytes = bundle_sz - offset_from_4bytes; |
-//printf("readed_bytes = %d\n", (int)readed_bytes); |
- memcpy(ptr_dest, src, readed_bytes); |
- ptr_dest += readed_bytes; |
- ptr_addr += readed_bytes; |
- if (readed_bytes > left_bytes) |
- left_bytes = 0; |
- else |
- left_bytes -= readed_bytes; |
-//printf("left_bytes = %d\n", (int)left_bytes); |
- } |
- |
- while (left_bytes) { |
-//printf("left_bytes = %d\n", (int)left_bytes); |
- res = ptrace(PTRACE_PEEKDATA, pid, ptr_addr, 0); |
-//printf("ptrace(PTRACE_PEEKDATA(%p) -> 0x%lX\n", ptr_addr, res); |
- if (0 != errno) { |
-//printf("Errno: %s\n", strerror(errno)); |
- break; |
- } |
- size_t rd_bytes = bundle_sz; |
- if (rd_bytes > left_bytes) |
- rd_bytes = left_bytes; |
- |
-//printf("rd_bytes = %d\n", (int)rd_bytes); |
- memcpy(ptr_dest, &res, rd_bytes); |
- readed_bytes += rd_bytes; |
- ptr_dest += rd_bytes; |
- ptr_addr += rd_bytes; |
- left_bytes -= rd_bytes; |
- } |
- if (NULL != readed_bytes_out) |
- *readed_bytes_out = readed_bytes; |
-//printf("size=%d readed_bytes=%d\n", (int)size, (int)readed_bytes); |
- return (size <= readed_bytes); |
-} |
- |
-bool DebugAPI::ReadThreadContext(pid_t pid, user_regs_struct* context) { |
- int ret = ptrace(PTRACE_GETREGS, pid, NULL, context); |
- return (0 == ret); |
-} |
- |
-bool DebugAPI::WriteThreadContext(pid_t pid, user_regs_struct* context) { |
- int ret = ptrace(PTRACE_SETREGS, pid, NULL, context); |
- return (0 == ret); |
-} |
- |
-bool DebugAPI::WaitForDebugEvent(DebugEvent* de) { |
- de->pid_ = 0; |
- de->signal_no_ = 0; |
- de->exit_code_ = 0; |
- de->process_state_ = PROCESS_STOPPED; |
- |
- int status = 0; |
- int options = WNOHANG | __WALL; |
- int res = waitpid(-1, &status, options); |
- if (-1 == res) |
- return false; |
- |
- bool event_received = (0 != res); |
- if (event_received) { |
- de->pid_ = res; |
- if (WIFEXITED(status)) { |
- de->process_state_ = PROCESS_EXITED; |
- de->exit_code_ = WEXITSTATUS(status); |
- } else if (WIFSIGNALED(status)) { |
- de->process_state_ = PROCESS_TERMINATED; |
- de->signal_no_ = WTERMSIG(status); |
- } else if (WIFSTOPPED(status)) { |
- de->process_state_ = PROCESS_STOPPED; |
- de->signal_no_ = WSTOPSIG(status); |
- } else if (WIFCONTINUED(status)) { |
- de->process_state_ = PROCESS_STOPPED; |
- de->signal_no_ = 0; |
- } |
- } |
- return event_received; |
-} |
- |
-} // namespace debug |
- |