2012-11-14 8 views
5

ptraceを使用して、自分のプログラムによって生成されたプログラムがどのシステムコールを呼び出すかを確認します。私はthis tutorialから始めました。答えは私のprevious questionです。マルチスレッドアプリケーションからのptraceの使用

#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <sys/reg.h> 
#include <sys/syscall.h> /* For SYS_write etc */ 

pid_t child; 

void run() 
{ 
    long orig_eax; 
    int status; 

    while(1) { 
      int pid = wait(&status); 
      if (pid == -1) { 
       perror("wait"); 
       kill(child, SIGKILL); 
       return; 
      } 
      printf("Got event from %d.\n", pid); 
      if(WIFEXITED(status)) 
       break; 
      orig_eax = ptrace(PTRACE_PEEKUSER, 
        pid, 8 * ORIG_RAX, NULL); 
      if (orig_eax == -1) { 
       perror("ptrace"); 
       kill(child, SIGKILL); 
       return; 
      } else { 
       printf("Syscall %ld called.\n", orig_eax); 
      } 
      ptrace(PTRACE_SYSCALL, 
        pid, NULL, NULL); 
    } 
} 

int main(int /*argc*/, char* argv[]) 
{ 

    child = fork(); 
    if(child == 0) { 
     ptrace(PTRACE_TRACEME, 0, NULL, NULL); 
     execl(argv[1], argv[1], NULL); 
    } 
    else { 
     printf("Child process id = %d.\n", child); 
     run(); 

    } 
    return 0; 
} 

それはかなりうまく機能:私は、生成されたプロセスが作る呼び出し、私は(SLES 11 64ビット)を使用しているプラ​​ットフォームにそれを適応させることによって、コードを修正し、一緒にすべてのシステムを出力し、次のテストコードを置きます:プログラムで作成されたシステムコールのIDを表示します(実際にはエントリに1回、終了時に1回、それぞれ2回ずつ出力しますが、今は関係ありません)。しかし、私のプログラムはシステムコールをチェックする以外のことをする必要があるので、別のスレッドにチェックを移すことにしました(私はC++よりもC++より快適です。それは重要だとは思わない)。もちろんこのプログラムでは、スレッドを開始してから参加します。

#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <sys/reg.h> 
#include <sys/syscall.h> /* For SYS_write etc */ 

#include <boost/thread.hpp> 


pid_t child; 

void run() 
{ 
    long orig_eax; 
    int status; 

    while(1) { 
      int pid = wait(&status); 
      if (pid == -1) { 
       perror("wait"); 
       kill(child, SIGKILL); 
       return; 
      } 
      printf("Got event from %d.\n", pid); 
      if(WIFEXITED(status)) 
       break; 
      orig_eax = ptrace(PTRACE_PEEKUSER, 
        pid, 8 * ORIG_RAX, NULL); 
      if (orig_eax == -1) { 
       perror("ptrace"); 
       kill(child, SIGKILL); 
       return; 
      } else { 
       printf("Syscall %ld called.\n", orig_eax); 
      } 
      ptrace(PTRACE_SYSCALL, 
        pid, NULL, NULL); 
    } 
} 

int main(int /*argc*/, char* argv[]) 
{ 

    child = fork(); 
    if(child == 0) { 
     ptrace(PTRACE_TRACEME, 0, NULL, NULL); 
     execl(argv[1], argv[1], NULL); 
    } 
    else { 
     printf("Child process id = %d.\n", child); 
     boost::thread t(run); 
     t.join(); 
    } 
    return 0; 
} 

今回私は、エラーメッセージが表示されます:

Child process id = 24682. 
Got event from 24682. 
ptrace: No such process 

これはなぜでしょうか?私は答えを探してみましたが、このようなものは何も見つかりませんでした。私はptraceが子プロセスによって開始されたスレッドをトレースしないことを発見しましたが、それは後で取り上げる必要があります。別のtheradから子プロセスをチェックすることさえ可能ですか?

他の奇妙なことは、私の実際のアプリケーションでは、基本的には同じことです(ただし、はるかに複雑なコンテキスト(クラス、mutexなど)からです)。 ptraceがエラーで返される代わりに、waitは子プロセスのシステムコールを返しません(子プロセスも停止しません)。一方、子プロセスが終了すると、waitは期待どおりに動作します。

答えて

1

私が言うことができる限り、ptraceはプロセスごとにただ1つのトレーサを許可します。つまり、アタッチしようとするとPTRACE_ATTACHで強制しようとすると、ptraceが指定されたプロセスにアタッチできなかったというエラーメッセージが表示されます。

したがって、スレッドが子プロセスに接続されていないため、この方法ではptraceにしようとすると、-ESRCHコードを送信するとエラーが表示されます。

さらに、this post hereを見ることができます。これは、あなたとは別の質問に答えるかもしれません。

+0

私のプロセスに専用のスレッドを持つことが助けになりました。 – petersohn

関連する問題