| Index: experimental/linux_oop_debugger/debug_api_linux.cc
|
| diff --git a/experimental/linux_oop_debugger/debug_api_linux.cc b/experimental/linux_oop_debugger/debug_api_linux.cc
|
| deleted file mode 100644
|
| index 0ec88c7d14429dafeaca9f7ccc8fa4f1c93c6d5b..0000000000000000000000000000000000000000
|
| --- a/experimental/linux_oop_debugger/debug_api_linux.cc
|
| +++ /dev/null
|
| @@ -1,647 +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 "debug_api_linux.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 (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 kOutputDebugStringSignal = SIGUSR1;
|
| -const int kOutputDebugStringSize = 4 * 1024;
|
| -} // namespace
|
| -
|
| -namespace debug {
|
| -bool DebugApi::PostASignal(pid_t pid, int signo, int sig_value) {
|
| - sigval val;
|
| - val.sival_int = sig_value;
|
| - return (0 == sigqueue(pid, signo, val));
|
| -}
|
| -
|
| -bool DebugApi::PostASignal(pid_t pid, int signo, void* sig_value) {
|
| - sigval val;
|
| - val.sival_ptr = sig_value;
|
| - return (0 == sigqueue(pid, signo, val));
|
| -}
|
| -
|
| -bool DebugApi::ReadDebugString(DebugEvent* de, std::string* string) {
|
| - if (DebugEvent::OUTPUT_DEBUG_STRING != de->event_code_)
|
| - return false;
|
| -
|
| - char buff[kOutputDebugStringSize + 1];
|
| - memset(buff, 'c', sizeof(buff));
|
| - void* addr = reinterpret_cast<void*>(de->signal_value_.sival_ptr);
|
| - size_t readed_bytes = 0;
|
| - bool res = ReadProcessMemory(de->process_id_,
|
| - addr,
|
| - buff,
|
| - sizeof(buff) - 1,
|
| - &readed_bytes);
|
| -// printf("ReadProcessMemory->%s readed_bytes = %d\n",
|
| -// res ? "ok" : "err", (int)readed_bytes);
|
| - if (0 == readed_bytes)
|
| - return false;
|
| -
|
| - buff[readed_bytes] = 0;
|
| - if (NULL != string)
|
| - *string = buff;
|
| - return true;
|
| -}
|
| -
|
| -bool DebugApi::ContinueDebugEvent(pid_t process_id, int signo) {
|
| - ptrace_result_t res = ptrace(PTRACE_CONT, process_id, 0, signo);
|
| -// printf("ptrace(PTRACE_CONT(pid=%d signo=%d) -> %ld\n",
|
| -// process_id, signo, res);
|
| - return (0 == res);
|
| -}
|
| -
|
| -bool DebugApi::GetNewChildPid(pid_t pid, pid_t* child_pid_out) {
|
| - // PTRACE_GETEVENTMSG
|
| - // TODO(garianov): implement
|
| - ptrace_result_t res = ptrace(PTRACE_GETEVENTMSG, pid, 0, 0);
|
| - 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);
|
| -
|
| - printf("In child: pid=%d ppid=%d\n", getpid(), getppid());
|
| - fflush(stdout);
|
| -
|
| - 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...
|
| - 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 ;
|
| -// PTRACE_O_TRACEEXEC |
|
| -// PTRACE_O_TRACEEXIT;
|
| - void* data = reinterpret_cast<void*>(mask);
|
| - ptrace_result_t res = ptrace(PTRACE_SETOPTIONS, pid, 0, data);
|
| - printf("Setup PTRACE_O_TRACEFORK option (0x%p) on pid=%d -> %ld\n",
|
| - data,
|
| - pid,
|
| - res);
|
| - fflush(stdout);
|
| - if (0 != res) {
|
| - printf("Error: ptrace(PTRACE_SETOPTIONS(pid=%d) -> %ld\n", pid, res);
|
| - printf("Errno: %s\n", strerror(errno));
|
| - }
|
| - return (0 != res);
|
| -}
|
| -
|
| -bool DebugApi::DebugBreak(pid_t pid) {
|
| - bool res = (0 == kill(pid, SIGSTOP));
|
| - if (!res) {
|
| - printf("kill failed\n");
|
| - printf("Errno: %s\n", strerror(errno));
|
| - fflush(stdout);
|
| - }
|
| - return res;
|
| -}
|
| -
|
| -bool DebugApi::SingleStep(pid_t pid) {
|
| - printf("SingleStep(%d)\n", pid);
|
| - ptrace_result_t res = ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
|
| - return (0 == res);
|
| -}
|
| -
|
| -
|
| -bool DebugApi::WriteProcessMemory(pid_t pid,
|
| - void* 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.
|
| - size_t offset = reinterpret_cast<size_t>(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, 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, data);
|
| - if (0 != res) {
|
| - printf("%d ptrace(PTRACE_POKEDATA) -> 0x%lX\n", __LINE__, 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::ReadProcessMemory(pid_t pid,
|
| - void* 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.
|
| - size_t offset = reinterpret_cast<size_t>(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::GetRax(pid_t pid, char** rax) {
|
| - user_regs_struct context;
|
| - if (!ReadThreadContext(pid, &context))
|
| - return false;
|
| -
|
| - if (NULL != rax)
|
| - *rax = reinterpret_cast<char*>(context.rax);
|
| - return true;
|
| -}
|
| -
|
| -bool DebugApi::GetIp(pid_t pid, char** ip) {
|
| - user_regs_struct context;
|
| - if (!ReadThreadContext(pid, &context))
|
| - return false;
|
| -
|
| - if (NULL != ip) {
|
| - *ip = reinterpret_cast<char*>(context.rip);
|
| - printf("ReadThreadContext-> ip = %p, ip = 0x%lx\n", *ip, context.rip);
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool DebugApi::SetIp(pid_t pid, char* ip) {
|
| - user_regs_struct context;
|
| - if (!ReadThreadContext(pid, &context))
|
| - return false;
|
| - if (NULL != ip)
|
| - context.rip = reinterpret_cast<u_int64_t>(ip);
|
| - return WriteThreadContext(pid, &context);
|
| -}
|
| -
|
| -bool DebugApi::ReadThreadContext(pid_t pid, user_regs_struct* context) {
|
| - int ret = ptrace(PTRACE_GETREGS, pid, NULL, context);
|
| -// printf("ptrace(PTRACE_GETREGS, -> %d\n", ret);
|
| - return (0 == ret);
|
| -}
|
| -
|
| -bool DebugApi::WriteThreadContext(pid_t pid, user_regs_struct* context) {
|
| - printf("calling ptrace (PTRACE_SETREGS, pid=%d\n", pid);
|
| - fflush(stdout);
|
| -
|
| - int ret = ptrace(PTRACE_SETREGS, pid, NULL, context);
|
| - printf("ptrace (PTRACE_SETREGS, -> %d\n", ret);
|
| - fflush(stdout);
|
| - return (0 == ret);
|
| -}
|
| -
|
| -#define BBB(x) printf("\t\"" #x "\" = \"%lX\",\n", context.x)
|
| -
|
| -void DebugApi::PrintThreadContext(const user_regs_struct& context) {
|
| - printf("context = {\n");
|
| - BBB(r15);
|
| - BBB(r14);
|
| - BBB(r13);
|
| - BBB(r12);
|
| - BBB(rbp);
|
| - BBB(rbx);
|
| - BBB(r11);
|
| - BBB(r10);
|
| - BBB(r9);
|
| - BBB(r8);
|
| - BBB(rax);
|
| - BBB(rcx);
|
| - BBB(rdx);
|
| - BBB(rsi);
|
| - BBB(rdi);
|
| - BBB(orig_rax);
|
| - BBB(rip);
|
| - BBB(cs);
|
| - BBB(eflags);
|
| - BBB(rsp);
|
| - BBB(ss);
|
| - BBB(fs_base);
|
| - BBB(gs_base);
|
| - BBB(ds);
|
| - BBB(es);
|
| - BBB(fs);
|
| - BBB(gs);
|
| - printf("}\n");
|
| -}
|
| -
|
| -bool DebugApi::WaitForDebugEvent(DebugEvent* de) {
|
| - int status = 0;
|
| - int options = WNOHANG; // | WUNTRACED | WCONTINUED;
|
| - options |= __WALL;
|
| - int res = waitpid(-1, &status, options);
|
| - if (-1 == res)
|
| - return false;
|
| -
|
| - bool recv_event = (0 != res);
|
| - if (recv_event) {
|
| - de->Reset();
|
| - de->process_id_ = res;
|
| -
|
| - user_regs_struct context;
|
| - if (ReadThreadContext(de->process_id_, &context)) {
|
| - de->ip_ = reinterpret_cast<char*>(context.rip);
|
| - }
|
| - siginfo_t si;
|
| - memset(&si, 0, sizeof(si));
|
| - ptrace_result_t res = ptrace(PTRACE_GETSIGINFO, de->process_id_, 0, &si);
|
| - // printf("ptrace(PTRACE_GETSIGINFO -> %ld\n", res);
|
| - if (0 == res) {
|
| - de->signal_code_ = si.si_code;
|
| - de->signal_value_ = si.si_value;
|
| - if ((SIGTRAP == de->signal_no_) ||
|
| - (SIGSEGV == de->signal_no_) ||
|
| - (SIGILL == de->signal_no_) ||
|
| - (SIGFPE == de->signal_no_) ||
|
| - (SIGBUS == de->signal_no_))
|
| - de->addr_ = reinterpret_cast<char*>(si.si_addr);
|
| -
|
| - if ((SIGTRAP == de->signal_no_) && (EVENT_CLONE == si.si_code)) {
|
| - // TODO(garianov): get children pid
|
| - // PTRACE_GETEVENTMSG
|
| - }
|
| - }
|
| -
|
| -
|
| - if (WIFEXITED(status)) {
|
| - de->event_code_ = DebugEvent::PROCESS_EXITED;
|
| - de->exit_code_ = WEXITSTATUS(status);
|
| - } else if (WIFSIGNALED(status)) {
|
| - de->event_code_ = DebugEvent::PROCESS_TERMINATED;
|
| - de->signal_no_ = WTERMSIG(status);
|
| - } else if (WIFSTOPPED(status)) {
|
| - de->event_code_ = DebugEvent::PROCESS_STOPPED;
|
| - de->signal_no_ = WSTOPSIG(status);
|
| -
|
| - if (SIGTRAP == de->signal_no_) {
|
| - de->event_code_ = DebugEvent::HIT_BREAKPOINT;
|
| - if (TRAP_TRACE == de->signal_code_)
|
| - de->event_code_ = DebugEvent::SINGLE_STEP_TRAP;
|
| - } else if (kOutputDebugStringSignal == de->signal_no_) {
|
| - de->event_code_ = DebugEvent::OUTPUT_DEBUG_STRING;
|
| - }
|
| - } else if (WIFCONTINUED(status)) {
|
| - de->event_code_ = DebugEvent::PROCESS_CONTINUED_WITH_SIGCONT;
|
| - }
|
| - }
|
| - return recv_event;
|
| -}
|
| -
|
| -bool DebugApi::EnableSingleStep(pid_t pid, bool enable) {
|
| - user_regs_struct context;
|
| - if (ReadThreadContext(pid, &context)) {
|
| - if (enable)
|
| - context.eflags |= 1 << 8;
|
| - else
|
| - context.eflags &= ~(1 << 8);
|
| - return WriteThreadContext(pid, &context);
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -void DebugEvent::Reset() {
|
| - memset(this, 0, sizeof(*this));
|
| -}
|
| -
|
| -#define BB(x, desc) case x: return #x ": " desc
|
| -
|
| -const char* GetSigCodeName(int signo, int sig_code) {
|
| - if (SIGILL == signo) {
|
| - switch (sig_code) {
|
| - BB(ILL_ILLOPC, "Illegal opcode");
|
| - BB(ILL_ILLADR, "Illegal addressing mode");
|
| - BB(ILL_ILLTRP, "Illegal trap");
|
| - BB(ILL_PRVOPC, "Privileged opcode");
|
| - BB(ILL_PRVREG, "Privileged register");
|
| - BB(ILL_COPROC, "Coprocessor error");
|
| - BB(ILL_BADSTK, "Internal stack error");
|
| - }
|
| - } else if (SIGFPE == signo) {
|
| - switch (sig_code) {
|
| - BB(FPE_INTDIV, "Integer divide by zero");
|
| - BB(FPE_INTOVF, "Integer overflow");
|
| - BB(FPE_FLTDIV, "Floating point divide by zero");
|
| - BB(FPE_FLTOVF, "Floating point overflow");
|
| - BB(FPE_FLTUND, "Floating point underflow");
|
| - BB(FPE_FLTRES, "Floating point inexact result");
|
| - BB(FPE_FLTINV, "Floating point invalid operation");
|
| - BB(FPE_FLTSUB, "Subscript out of range");
|
| - }
|
| - } else if (SIGSEGV == signo) {
|
| - switch (sig_code) {
|
| - BB(SEGV_MAPERR, "Address not mapped to object");
|
| - BB(SEGV_ACCERR, "Invalid permissions for mapped object");
|
| - }
|
| - } else if (SIGBUS == signo) {
|
| - switch (sig_code) {
|
| - BB(BUS_ADRALN, "Invalid address alignment");
|
| - BB(BUS_ADRERR, "Non-existant physical address");
|
| - BB(BUS_OBJERR, "Object specific hardware error");
|
| - }
|
| - } else if (SIGTRAP == signo) {
|
| - switch (sig_code) {
|
| - BB(TRAP_BRKPT, "Process breakpoint");
|
| - BB(TRAP_TRACE, "Process trace trap, aka single step");
|
| - BB(EVENT_FORK, "");
|
| - BB(EVENT_VFORK, "");
|
| - BB(EVENT_CLONE, "");
|
| - BB(EVENT_EXEC, "");
|
| - BB(EVENT_VFORK_DONE, "");
|
| - BB(EVENT_EXIT, "");
|
| - }
|
| - } else if (SIGCHLD == signo) {
|
| - switch (sig_code) {
|
| - BB(CLD_EXITED, "Child has exited");
|
| - BB(CLD_KILLED, "Child was killed");
|
| - BB(CLD_DUMPED, "Child terminated abnormally");
|
| - BB(CLD_TRAPPED, "Traced child has trapped");
|
| - BB(CLD_STOPPED, "Child has stopped");
|
| - BB(CLD_CONTINUED, "Stopped child has continued");
|
| - }
|
| - } else if (SIGPOLL == signo) {
|
| - switch (sig_code) {
|
| - BB(POLL_IN, "Data input available");
|
| - BB(POLL_OUT, "Output buffers available");
|
| - BB(POLL_MSG, "Input message available");
|
| - BB(POLL_ERR, "I/O error");
|
| - BB(POLL_PRI, "High priority input available");
|
| - BB(POLL_HUP, "Device disconnected");
|
| - }
|
| - }
|
| - switch (sig_code) {
|
| - BB(SI_ASYNCNL, "Sent by asynch name lookup completion");
|
| - BB(SI_TKILL, "Sent by tkill");
|
| - BB(SI_SIGIO, "Sent by queued SIGIO");
|
| - BB(SI_ASYNCIO, "Sent by AIO completion");
|
| - BB(SI_MESGQ, "Sent by real time mesq state change");
|
| - BB(SI_TIMER, "Sent by timer expiration");
|
| - BB(SI_QUEUE, "Sent by sigqueue");
|
| - BB(SI_USER, "Sent by kill, sigsend, raise");
|
| - BB(SI_KERNEL, "Send by kernel");
|
| - }
|
| - return "";
|
| -}
|
| -
|
| -const char* GetSignalName(int signo) {
|
| - switch (signo) {
|
| - BB(SIGHUP, "Hangup (POSIX)");
|
| - BB(SIGINT, "Interrupt (ANSI)");
|
| - BB(SIGQUIT, "Quit (POSIX)");
|
| - BB(SIGILL, "Illegal instruction (ANSI)");
|
| - BB(SIGTRAP, "Trace trap (POSIX)");
|
| - BB(SIGABRT, "==SIGIOT. Abort (ANSI) == IOT trap (4.2 BSD)");
|
| - BB(SIGBUS, "BUS error (4.2 BSD)");
|
| - BB(SIGFPE, "Floating-point exception (ANSI)");
|
| - BB(SIGKILL, "Kill, unblockable (POSIX)");
|
| - BB(SIGUSR1, "User-defined signal 1 (POSIX)");
|
| - BB(SIGSEGV, "Segmentation violation (ANSI)");
|
| - BB(SIGUSR2, "User-defined signal 2 (POSIX)");
|
| - BB(SIGPIPE, "Broken pipe (POSIX)");
|
| - BB(SIGALRM, "Alarm clock (POSIX)");
|
| - BB(SIGTERM, "Termination (ANSI)");
|
| - BB(SIGSTKFLT, "Stack fault");
|
| - BB(SIGCHLD, "Child status has changed (POSIX)");
|
| - BB(SIGCONT, "Continue (POSIX)");
|
| - BB(SIGSTOP, "Stop, unblockable (POSIX)");
|
| - BB(SIGTSTP, "Keyboard stop (POSIX)");
|
| - BB(SIGTTIN, "Background read from tty (POSIX)");
|
| - BB(SIGTTOU, "Background write to tty (POSIX)");
|
| - BB(SIGURG, "Urgent condition on socket (4.2 BSD)");
|
| - BB(SIGXCPU, "CPU limit exceeded (4.2 BSD)");
|
| - BB(SIGXFSZ, "File size limit exceeded (4.2 BSD)");
|
| - BB(SIGVTALRM, "Virtual alarm clock (4.2 BSD)");
|
| - BB(SIGPROF, "Profiling alarm clock (4.2 BSD)");
|
| - BB(SIGWINCH, "Window size change (4.3 BSD, Sun)");
|
| - BB(SIGIO,
|
| - "I/O now possible (4.2 BSD) /"
|
| - "Pollable event occurred (System V)");
|
| - BB(SIGPWR, "Power failure restart (System V)");
|
| - BB(SIGSYS, "Bad system call");
|
| - }
|
| - return "";
|
| -}
|
| -
|
| -#define AAA(x) case x: ev_name = #x; break
|
| -
|
| -void DebugEvent::Print() {
|
| - const char* ev_name = "UNKNOWN";
|
| - switch (event_code_) {
|
| - AAA(HIT_BREAKPOINT);
|
| - AAA(OUTPUT_DEBUG_STRING);
|
| - AAA(SINGLE_STEP_TRAP);
|
| - AAA(PROCESS_TERMINATED);
|
| - AAA(PROCESS_EXITED);
|
| - AAA(PROCESS_STOPPED);
|
| - AAA(PROCESS_CONTINUED_WITH_SIGCONT);
|
| - }
|
| -
|
| - printf("\"DebugEvent\" : {\n");
|
| - printf("\t\"process_id_\" : \"%d\",\n", process_id_);
|
| - printf("\t\"event_code_\" : \"%s\",\n", ev_name);
|
| -
|
| - printf("\t\"signal_no_\" : \"%d\",", signal_no_);
|
| - if (0 != signal_no_)
|
| - printf(" //%s", GetSignalName(signal_no_));
|
| - printf("\n");
|
| -
|
| - printf("\t\"signal_code_\" : \"%d\",", signal_code_);
|
| - const char* sig_code_name = GetSigCodeName(signal_no_, signal_code_);
|
| - if (strlen(sig_code_name) > 0 )
|
| - printf(" //%s", sig_code_name);
|
| - printf("\n");
|
| -
|
| - printf("\t\"exit_code_\" : \"%d\",\n", exit_code_);
|
| - printf("\t\"ip_\" : \"%p\",\n", ip_);
|
| - printf("\t\"addr_\" : \"%p\",\n", addr_);
|
| - printf("}\n");
|
| -}
|
| -} // namespace debug
|
| -
|
|
|