帖子末尾的代码是该问题的一个答案。
您可以拥有一个跟踪进程的线程。
如果有人感兴趣,我正在试验的问题是,由于一些难以理解的原因,跟踪线程并不是发送所有跟踪命令的线程。其中一个负责调用fork并负责trace,另一个负责发送
- ptrace(PTRACE_CONT, childPID, 0, 0);
- ptrace(PTRACE_GETREGS,childPID,0,寄存器);
结果错误是: ptrace (PTRACE_GETREGS,..) 无法获取寄存器:没有这样的过程
#include <pthread.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/reg.h>
#include <sys/user.h>
#define NUM_THREADS 9
int childPID;
int fatherPID;
void print_registers(struct user_regs_struct *registers){
printf("\tReg ebx 0x%lx\n",registers->ebx);
printf("\tReg ecx 0x%lx\n",registers->ecx);
printf("\tReg edx 0x%lx\n",registers->edx);
printf("\tReg esi 0x%lx\n",registers->esi);
printf("\tReg edi 0x%lx\n",registers->edi);
printf("\tReg ebp 0x%lx\n",registers->ebp);
printf("\tReg eax 0x%lx\n",registers->eax);
printf("\tReg xds 0x%lx\n",registers->xds);
printf("\tReg xes 0x%lx\n",registers->xes);
printf("\tReg xfs 0x%lx\n",registers->xfs);
printf("\tReg xgs 0x%lx\n",registers->xgs);
printf("\tReg orig_eax 0x%lx\n",registers->orig_eax);
printf("\tReg eip 0x%lx\n",registers->eip);
printf("\tReg xcs 0x%lx\n",registers->xcs);
printf("\tReg eflags 0x%lx\n",registers->eflags);
printf("\tReg esp 0x%lx\n",registers->esp);
printf("\tReg xss 0x%lx\n",registers->xss);
}
int load(char * execPath){
switch( childPID=fork() ){
case -1:
perror("fork()");
return -1;
case 0 :
if( access(execPath, X_OK)==-1){
printf("\tAcces denied to\n",execPath);
}
else {
printf("\tChild Process pid :%d %d\n",childPID,getpid());
if(ptrace(PTRACE_TRACEME, 0, NULL, NULL)<0){
perror("ptrace(PTRACE_TRACEME)");
return -1;
}
execve(execPath,NULL,NULL);
perror("execve()");
}
return -1;
default:
wait(NULL);
fatherPID=getpid();
printf("\tParent Process pid :%d %d\n",fatherPID,childPID);
if (ptrace(PTRACE_SETOPTIONS, childPID, 0, PTRACE_O_TRACEEXIT)){
perror("stopper: ptrace(PTRACE_SETOPTIONS, ...)");
return -1;
}
break;
}
return -1;
}
void registers(){
printf("\t@@Command get_registers@\n");
struct user_regs_struct * registers = (struct user_regs_struct*)(calloc(1, sizeof(struct user_regs_struct)));
long ret = ptrace (PTRACE_GETREGS, childPID, 0, registers);
if (ret <0) perror("ptrace (PTRACE_GETREGS,..) Couldn't get registers");
print_registers(registers);
free(registers);
}
int continuE(){
int status = 0;
int signo;
long long_var=0;
// to continue the execution is needed to trigger the event
while (1) {
ptrace(PTRACE_CONT, childPID, 0, 0);
waitpid( childPID, &status, 0);
if (WIFEXITED(status))
printf("Child exited by %d\n",WEXITSTATUS(status));
if (WIFSIGNALED(status))
printf(" child process terminated by a signal %d \n",WTERMSIG(status) );
if (WIFSTOPPED(status)) {
signo = WSTOPSIG(status);
//printf("Child stopped by %d\n",signo);
}
// we had the sigtrap and we are at the exec
if (status>>8 == (SIGTRAP | (PTRACE_EVENT_EXEC<<8))){
printf("\t###Stopped the tracee at EXEC, with status %d###\n",WEXITSTATUS(status));
ptrace(PTRACE_GETEVENTMSG, childPID,0,&long_var);
printf("\t###PTRACE_GETEVENTMSG result %lu ,%d ###\n",long_var,WEXITSTATUS(long_var));
}
// we have a sigtrap and we are on the exit
// we could think to take out PTRACE_O_TRACEEXIT
if (status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8))){
printf("\t###Stopped the tracee at EXIT###\n");
signo= SIGHUP;
}
// normal cases
if ((signo == SIGTRAP) || (signo == SIGTERM) ||(signo ==SIGINT) || (signo == SIGHUP)
|| ( signo == SIGSEGV) ){
break;
}
}
return signo;
}
void *work(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
load("/home/rtems/plibeagleeye/Plib/Tests/bin/stanford.o");
registers();
continuE();
registers();
pthread_exit(NULL);
}
void *work2(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
int rc;
long *taskids;
void *status;
taskids = (long *) malloc( NUM_THREADS * sizeof(long));
long t=0;
/* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
taskids[t] = 0;
rc = pthread_create(&threads[t], &attr, work, (void *)taskids[t]);
for(t=1; t<NUM_THREADS; t++){
taskids[t] = t;
printf("Creating thread %ld\n", t);
rc = pthread_create(&threads[t], &attr, work2, (void *)taskids[t]);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_attr_destroy(&attr);
for(t=0; t<NUM_THREADS; t++){
rc = pthread_join(threads[t], &status);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status);
}
printf("Ciaoz all threads finished their jobs\n");
free(taskids);
/* Last thing that main() should do */
pthread_exit(NULL);
return 0;
}
真正让我惊讶的是,没有迹象表明哪个线程是示踪剂。ptrace(PTRACE_TRACEME, 0, NULL, NULL) 0 似乎工作得很好。