|  |  |  | @ -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; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | 
 |