12

DTrace を呼び出して、ユーザーが指定したプログラムをトレースするツールを作成しています。

私のツールが dtrace -c を使用してプログラムを DTrace のサブプロセスとして実行する場合、プログラムに引数を渡すことができないだけでなく、プログラムは DTrace のすべての権限で実行されます。 Mac OS X)。これにより、機能するはずの特定の機能が壊れてしまい、明らかに、機能しないはずの非常に多くのことが可能になります。

私が知っている他の解決策は、自分でプログラムを開始し、それを送信して一時停止しSIGSTOP、その PID を に渡しdtrace -p、次に送信して続行することSIGCONTです。問題は、DTrace がシンボル情報を収集している間、プログラムがトレースされずに数秒間実行されるか、プロセスを続行する前に数秒間スリープすると、DTrace がobjc<pid>:<class>:<method>:entry一致するプローブがないと文句を言うことです。

root としてではなく、ユーザーのアカウントでプログラムを実行し、DTrace で最初から追跡できるようにする方法はありますか?

4

7 に答える 7

4

このスクリプトは、パラメーターとして DTrace に監視する実行可能ファイルの名前 (アプリの場合、これは info.plist の CFBundleExecutable) を取ります (このスクリプトの実行後にターゲット アプリを起動できます)。

string gTarget;     /* the name of the target executable */

dtrace:::BEGIN
{
    gTarget = $$1;  /* get the target execname from 1st DTrace parameter */

    /*
    * Note: DTrace's execname is limited to 15 characters so if $$1 has more
    * than 15 characters the simple string comparison "($$1 == execname)"
    * will fail. We work around this by copying the parameter passed in $$1
    * to gTarget and truncating that to 15 characters.
    */

    gTarget[15] = 0;        /* truncate to 15 bytes */
    gTargetPID = -1;        /* invalidate target pid */
}

/*
* capture target launch (success)
*/
proc:::exec-success
/
    gTarget == execname
/
{
    gTargetPID = pid;
}

/*
*   detect when our target exits
*/
syscall::*exit:entry
/
    pid == gTargetPID
/
{
    gTargetPID = -1;        /* invalidate target pid */
}

/*
* capture open arguments
*/
syscall::open*:entry
/
    ((pid == gTargetPID) || progenyof(gTargetPID))
/
{
    self->arg0 = arg0;
    self->arg1 = arg1;
}

/*
* track opens
*/
syscall::open*:return
/
    ((pid == gTargetPID) || progenyof(gTargetPID))
/
{
    this->op_kind = ((self->arg1 & O_ACCMODE) == O_RDONLY) ? "READ" : "WRITE";
    this->path0 = self->arg0 ? copyinstr(self->arg0) : "<nil>";

    printf("open for %s: <%s> #%d",
        this->op_kind,
        this->path0,
        arg0);
}
于 2012-07-11T16:58:22.653 に答える
3

他の答えがうまくいかない場合は、プログラムを gdb で実行し、main (またはそれ以前) で中断し、pid を取得して、スクリプトを開始できますか? 私は過去にそれを試しましたが、うまくいくようでした。

于 2009-07-30T07:12:09.070 に答える
2

ある種のシグナル(必ずしも文字通りのシグナルではなく、準備ができていることを示すだけです)を待機し、ターゲットを exec() するランチャープログラムを作成します。ここで、ランチャー プログラムを dtrace -p します。dtrace が起動したら、ランチャーを放します。

于 2009-07-30T03:13:29.047 に答える
1

dtruss には、トレースするプロセスの名前を指定できるオプションがあります ( https://stackoverflow.com/a/11706251/970301-nの @kenorb の回答の後半部分のクレジット)。したがって、次のようなものがそれを行う必要があります。

sudo dtruss -n "$program"
$program
于 2013-12-26T22:42:14.763 に答える
0

関連する質問に対する私の回答を参照してください。[原文のまま]。

基本的に、DTrace が起動するまで 1 秒待機し (競合状態で申し訳ありません)、そのプロセスの PID をスヌープする (ルート以外の) バックグラウンド プロセスを開始できます。

sudo true && \
(sleep 1; cat /etc/hosts) &; \
sudo dtrace -n 'syscall:::entry /pid == $1/ {@[probefunc] = count();}' $! \
&& kill $!

リンクされた回答の完全な説明。

于 2017-06-25T18:56:29.723 に答える