From a969f9893f29d570c9d9b5a801e450560081d8e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Wed, 2 Mar 2011 22:23:24 +0100 Subject: [PATCH] Fix wine process suspend/resume. They use same mechanism as attach/detach now. --- library/DFProcess-linux-base.cpp | 149 ----------------------------- library/DFProcess-linux-wine.cpp | 114 ++++++++++++++++++++++ library/DFProcess-linux.cpp | 159 +++++++++++++++++++++++++++++++ library/private/LinuxProcess.h | 8 -- 4 files changed, 273 insertions(+), 157 deletions(-) diff --git a/library/DFProcess-linux-base.cpp b/library/DFProcess-linux-base.cpp index f704d384e..42a21664e 100644 --- a/library/DFProcess-linux-base.cpp +++ b/library/DFProcess-linux-base.cpp @@ -54,10 +54,6 @@ bool LinuxProcessBase::isIdentified() LinuxProcessBase::~LinuxProcessBase() { - if(attached) - { - detach(); - } // destroy our copy of the memory descriptor if(my_descriptor) delete my_descriptor; @@ -107,151 +103,6 @@ void LinuxProcessBase::getMemRanges( vector & ranges ) } } -bool LinuxProcessBase::asyncSuspend() -{ - return suspend(); -} - -bool LinuxProcessBase::suspend() -{ - int status; - if(!attached) - return false; - if(suspended) - return true; - if (kill(my_pid, SIGSTOP) == -1) - { - // no, we got an error - perror("kill SIGSTOP error"); - return false; - } - while(true) - { - // we wait on the pid - pid_t w = waitpid(my_pid, &status, 0); - if (w == -1) - { - // child died - perror("DF exited during suspend call"); - return false; - } - // stopped -> let's continue - if (WIFSTOPPED(status)) - { - break; - } - } - suspended = true; - return true; -} - -bool LinuxProcessBase::forceresume() -{ - return resume(); -} - -bool LinuxProcessBase::resume() -{ - if(!attached) - return false; - if(!suspended) - return true; - if (ptrace(PTRACE_CONT, my_pid, NULL, NULL) == -1) - { - // no, we got an error - perror("ptrace resume error"); - return false; - } - suspended = false; - return true; -} - - -bool LinuxProcessBase::attach() -{ - int status; - if(attached) - { - if(!suspended) - return suspend(); - return true; - } - // can we attach? - if (ptrace(PTRACE_ATTACH , my_pid, NULL, NULL) == -1) - { - // no, we got an error - perror("ptrace attach error"); - cerr << "attach failed on pid " << my_pid << endl; - return false; - } - while(true) - { - // we wait on the pid - pid_t w = waitpid(my_pid, &status, 0); - if (w == -1) - { - // child died - perror("wait inside attach()"); - return false; - } - // stopped -> let's continue - if (WIFSTOPPED(status)) - { - break; - } - } - suspended = true; - - int proc_pid_mem = open(memFile.c_str(),O_RDONLY); - if(proc_pid_mem == -1) - { - ptrace(PTRACE_DETACH, my_pid, NULL, NULL); - cerr << memFile << endl; - cerr << "couldn't open /proc/" << my_pid << "/mem" << endl; - perror("open(memFile.c_str(),O_RDONLY)"); - return false; - } - else - { - attached = true; - - memFileHandle = proc_pid_mem; - return true; // we are attached - } -} - -bool LinuxProcessBase::detach() -{ - if(!attached) return true; - if(!suspended) suspend(); - int result = 0; - // close /proc/PID/mem - result = close(memFileHandle); - if(result == -1) - { - cerr << "couldn't close /proc/"<< my_pid <<"/mem" << endl; - perror("mem file close"); - return false; - } - else - { - // detach - result = ptrace(PTRACE_DETACH, my_pid, NULL, NULL); - if(result == -1) - { - cerr << "couldn't detach from process pid" << my_pid << endl; - perror("ptrace detach"); - return false; - } - else - { - attached = false; - return true; - } - } -} - - void LinuxProcessBase::read (const uint32_t offset, const uint32_t size, uint8_t *target) { if(size == 0) return; diff --git a/library/DFProcess-linux-wine.cpp b/library/DFProcess-linux-wine.cpp index 073efcaa2..29fcd9b75 100644 --- a/library/DFProcess-linux-wine.cpp +++ b/library/DFProcess-linux-wine.cpp @@ -39,6 +39,20 @@ namespace { MicrosoftSTL stl; public: WineProcess(uint32_t pid, VersionInfoFactory * factory); + ~WineProcess() + { + if(attached) + { + detach(); + } + } + bool attach(); + bool detach(); + + bool suspend(); + bool asyncSuspend(); + bool resume(); + bool forceresume(); const std::string readSTLString (uint32_t offset); size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); @@ -131,3 +145,103 @@ string WineProcess::readClassName (uint32_t vptr) { return stl.readClassName(vptr); } + +bool WineProcess::asyncSuspend() +{ + return suspend(); +} + +bool WineProcess::suspend() +{ + int status; + if(suspended) + return true; + // can we attach? + if (ptrace(PTRACE_ATTACH , my_pid, NULL, NULL) == -1) + { + // no, we got an error + perror("ptrace attach error"); + cerr << "attach failed on pid " << my_pid << endl; + return false; + } + while(true) + { + // we wait on the pid + pid_t w = waitpid(my_pid, &status, 0); + if (w == -1) + { + // child died + perror("wait inside attach()"); + return false; + } + // stopped -> let's continue + if (WIFSTOPPED(status)) + { + break; + } + } + int proc_pid_mem = open(memFile.c_str(),O_RDONLY); + if(proc_pid_mem == -1) + { + ptrace(PTRACE_DETACH, my_pid, NULL, NULL); + cerr << memFile << endl; + cerr << "couldn't open /proc/" << my_pid << "/mem" << endl; + perror("open(memFile.c_str(),O_RDONLY)"); + return false; + } + else + { + attached = suspended = true; + memFileHandle = proc_pid_mem; + return true; // we are attached + } +} + +bool WineProcess::forceresume() +{ + return resume(); +} + +bool WineProcess::resume() +{ + if(!suspended) + return true; + int result = 0; + // close /proc/PID/mem + result = close(memFileHandle); + if(result == -1) + { + cerr << "couldn't close /proc/"<< my_pid <<"/mem" << endl; + perror("mem file close"); + return false; + } + else + { + // detach + result = ptrace(PTRACE_DETACH, my_pid, NULL, NULL); + if(result == -1) + { + cerr << "couldn't detach from process pid" << my_pid << endl; + perror("ptrace detach"); + return false; + } + else + { + attached = suspended = false; + return true; + } + } +} + + +bool WineProcess::attach() +{ + if(suspended) return true; + return suspend(); +} + +bool WineProcess::detach() +{ + if(!suspended) return true; + return resume(); +} diff --git a/library/DFProcess-linux.cpp b/library/DFProcess-linux.cpp index 216f4babe..d6d21edfa 100644 --- a/library/DFProcess-linux.cpp +++ b/library/DFProcess-linux.cpp @@ -35,6 +35,20 @@ namespace { { public: NormalProcess(uint32_t pid, VersionInfoFactory * known_versions); + ~NormalProcess() + { + if(attached) + { + detach(); + } + } + bool attach(); + bool detach(); + + bool suspend(); + bool asyncSuspend(); + bool resume(); + bool forceresume(); const std::string readSTLString (uint32_t offset); size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); @@ -137,3 +151,148 @@ string NormalProcess::readClassName (uint32_t vptr) size_t end = raw.length(); return raw.substr(start,end-start); } + +bool NormalProcess::asyncSuspend() +{ + return suspend(); +} + +bool NormalProcess::suspend() +{ + int status; + if(!attached) + return false; + if(suspended) + return true; + if (kill(my_pid, SIGSTOP) == -1) + { + // no, we got an error + perror("kill SIGSTOP error"); + return false; + } + while(true) + { + // we wait on the pid + pid_t w = waitpid(my_pid, &status, 0); + if (w == -1) + { + // child died + perror("DF exited during suspend call"); + return false; + } + // stopped -> let's continue + if (WIFSTOPPED(status)) + { + break; + } + } + suspended = true; + return true; +} + +bool NormalProcess::forceresume() +{ + return resume(); +} + +bool NormalProcess::resume() +{ + if(!attached) + return false; + if(!suspended) + return true; + if (ptrace(PTRACE_CONT, my_pid, NULL, NULL) == -1) + { + // no, we got an error + perror("ptrace resume error"); + return false; + } + int status; + suspended = false; + return true; +} + + +bool NormalProcess::attach() +{ + int status; + if(attached) + { + if(!suspended) + return suspend(); + return true; + } + // can we attach? + if (ptrace(PTRACE_ATTACH , my_pid, NULL, NULL) == -1) + { + // no, we got an error + perror("ptrace attach error"); + cerr << "attach failed on pid " << my_pid << endl; + return false; + } + while(true) + { + // we wait on the pid + pid_t w = waitpid(my_pid, &status, 0); + if (w == -1) + { + // child died + perror("wait inside attach()"); + return false; + } + // stopped -> let's continue + if (WIFSTOPPED(status)) + { + break; + } + } + suspended = true; + + int proc_pid_mem = open(memFile.c_str(),O_RDONLY); + if(proc_pid_mem == -1) + { + ptrace(PTRACE_DETACH, my_pid, NULL, NULL); + cerr << memFile << endl; + cerr << "couldn't open /proc/" << my_pid << "/mem" << endl; + perror("open(memFile.c_str(),O_RDONLY)"); + return false; + } + else + { + attached = true; + + memFileHandle = proc_pid_mem; + return true; // we are attached + } +} + +bool NormalProcess::detach() +{ + if(!attached) return true; + if(!suspended) suspend(); + int result = 0; + // close /proc/PID/mem + result = close(memFileHandle); + if(result == -1) + { + cerr << "couldn't close /proc/"<< my_pid <<"/mem" << endl; + perror("mem file close"); + return false; + } + else + { + // detach + result = ptrace(PTRACE_DETACH, my_pid, NULL, NULL); + if(result == -1) + { + cerr << "couldn't detach from process pid" << my_pid << endl; + perror("ptrace detach"); + return false; + } + else + { + attached = false; + return true; + } + } +} diff --git a/library/private/LinuxProcess.h b/library/private/LinuxProcess.h index e3e04cb35..bafe786ac 100644 --- a/library/private/LinuxProcess.h +++ b/library/private/LinuxProcess.h @@ -43,14 +43,6 @@ namespace DFHack LinuxProcessBase(uint32_t pid); ~LinuxProcessBase(); - bool attach(); - bool detach(); - - bool suspend(); - bool asyncSuspend(); - bool resume(); - bool forceresume(); - void readQuad(const uint32_t address, uint64_t & value); void writeQuad(const uint32_t address, const uint64_t value);