Fix wine process suspend/resume. They use same mechanism as attach/detach now.

develop
Petr Mrázek 2011-03-02 22:23:24 +01:00
parent 9b2c071cb5
commit a969f9893f
4 changed files with 273 additions and 157 deletions

@ -54,10 +54,6 @@ bool LinuxProcessBase::isIdentified()
LinuxProcessBase::~LinuxProcessBase() LinuxProcessBase::~LinuxProcessBase()
{ {
if(attached)
{
detach();
}
// destroy our copy of the memory descriptor // destroy our copy of the memory descriptor
if(my_descriptor) if(my_descriptor)
delete my_descriptor; delete my_descriptor;
@ -107,151 +103,6 @@ void LinuxProcessBase::getMemRanges( vector<t_memrange> & 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) void LinuxProcessBase::read (const uint32_t offset, const uint32_t size, uint8_t *target)
{ {
if(size == 0) return; if(size == 0) return;

@ -39,6 +39,20 @@ namespace {
MicrosoftSTL stl; MicrosoftSTL stl;
public: public:
WineProcess(uint32_t pid, VersionInfoFactory * factory); 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); const std::string readSTLString (uint32_t offset);
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); 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); 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();
}

@ -35,6 +35,20 @@ namespace {
{ {
public: public:
NormalProcess(uint32_t pid, VersionInfoFactory * known_versions); 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); const std::string readSTLString (uint32_t offset);
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); 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(); size_t end = raw.length();
return raw.substr(start,end-start); 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;
}
}
}

@ -43,14 +43,6 @@ namespace DFHack
LinuxProcessBase(uint32_t pid); LinuxProcessBase(uint32_t pid);
~LinuxProcessBase(); ~LinuxProcessBase();
bool attach();
bool detach();
bool suspend();
bool asyncSuspend();
bool resume();
bool forceresume();
void readQuad(const uint32_t address, uint64_t & value); void readQuad(const uint32_t address, uint64_t & value);
void writeQuad(const uint32_t address, const uint64_t value); void writeQuad(const uint32_t address, const uint64_t value);