機械翻訳について

PIDプロバイダ

pidプロバイダは、ユーザー・プロセス(関数entryreturnの両方)および任意の命令をトレースします。

PIDプローブ

プローブは、そのプロバイダ、モジュール、関数、および名前に名前を付けることによって完全に指定されます。

pidプロバイダ名はpid$pidで、$pidは目的のプロセスのプロセスID (pid)です。 プロセスIDを指定する必要があります(ワイルドカードは指定しません)。ただし、シンボリック値を使用できます。 次に例を示します:

sudo dtrace -lP pid

プロセスIDが指定されていないため、前のコマンドでプローブが見つかりません。 かわりに、次のようなコマンドを使用します:

sudo dtrace -ln 'pid1234567:libc::entry'
sudo dtrace -p 1234567 -ln 'pid$target:libc::entry'
sudo dtrace -c ./a.out -n 'pid$target:libc::entry { trace("hi"); }'
sudo dtrace -n 'pid$1:libc::entry { trace("hi"); }'

この例では、1234567は架空のpid値で、システムに適したpid値で置き換える必要があります。$targetは、-pまたは-cで指定されたターゲット・コマンドのpidに展開されるマクロで、$1dtraceのコマンドライン引数です。 この例では、次のように表示されます:

1234567

モジュール名は、実行可能ファイル内のモジュールです。 特殊なケースには、実行可能ファイルのロード・オブジェクト(a.outと呼ばれる場合があります)と、次の方法で参照できる共有ライブラリが含まれます:

  • フル・パス名(/usr/lib/libc.so.1など)。

  • ベース名(libc.so.1など)。

  • 最初のベース名は、.サフィクス(libc.solibcなど)まで一致します。

関数名は、通常、プローブが配置されている関数の名前です。 関数がコンパイラによってインライン化されている場合は、pidトレースには使用できません。

特別な関数-があります。 この場合、モジュール名は空白にするか、a.outモジュールを参照する必要があります。 さらに、プローブ名は、a.outモジュール内の命令に対する絶対16進オフセットである必要があります。

プローブ名は次のいずれかです:

  • entry: 関連する関数のエントリを参照します。

  • return: 関連する関数からの戻り値を示します。 DTraceの従来の実装では、プローブはなんらかの戻り命令で起動されました。 現在の実装では、returnuretprobeを使用して実装され、呼出し側関数で起動されます。

  • 命令オフセット。 先頭の0xのない16進オフセットは、指定された関数に対する相対ですが、関数名が-の場合、絶対オフセットです。

pidプローブの引数

entryプローブの場合、プローブ引数はプローブされた関数の引数と同じです。

returnプローブの場合、arg1はプローブされた関数の戻り値です。

オフセット・プローブの場合、プローブ引数はありません。

pidの例

関数foo()をコールするmain.cという名前の次のプログラムについて考えてみます:

 int foo(int i, int j) {
     return (i + j) - 6666;
 }

 int main(int c, char **v) {
     return foo(1234, 8765) != 3333;
 }

foo()の引数は1234および8765で、戻り値は3333です。

プログラムをコンパイルします:

gcc main.c

D1.dという名前のDスクリプトを作成します:

 pid$target:a.out:foo:entry,
 pid$target:a.out:foo:return
 {
     printf("%x %s:%s\n", uregs[R_PC], probefunc, probename);
 }

 pid$target:a.out:foo:entry
 {
     printf("entry args: %d %d\n", arg0, arg1);
 }

 pid$target:a.out:foo:return
 {
     printf("return arg: %d\n", arg1);
 }

Dスクリプトを実行します:

sudo dtrace -c ./a.out -qs D1.d

出力は次のようになります:

 401106 foo:entry
 entry args: 1234 8765
 40113d foo:return
 return arg: 3333

foo() entryおよびreturnでは、プローブの起動時に、ターゲット・スレッドの保存されたユーザー・モード・レジスタ値から、プローブ関数および名前とともにPCを出力します。 さらに、エントリ・プローブの2つの引数とリターン・プローブのarg1を出力します。 foo()エントリの引数が1234および8765で、戻り値が3333であることが予想されます。

PCを理解するには、objdumpを実行します:

 objdump -d a.out

出力は次のようになります:

 0000000000401106 <foo>:
   401106:    55                       push   %rbp
   401107:    48 89 e5                 mov    %rsp,%rbp
   40110a:    89 7d fc                 mov    %edi,-0x4(%rbp)
   [...]

 000000000040111f <main>:
   40111f:    55                       push   %rbp
   [...]
   401138:    e8 c9 ff ff ff           callq  401106 <foo>
   40113d:    83 f0 01                 xor    $0x1,%eax
   [...]

出力の多くは抑制されていますが、Dスクリプトで報告されているように、foo() entry PCは0x401106です。 リターンPCは0x40113dで、これはfoo()コールの直後のPCです。

ノート:

DTraceの他のバージョンでは、戻りPCはコールされた関数の戻り命令用です。 Linuxでは、リターンuprobe (uretprobe)を使用して、コール元で指示を返します。

最後に、特定の命令を調べる方法を説明します。 foo()、PC 0x40110aで3番目の命令を選択します。 これは、foo()の先頭から4バイトの相対オフセットにあります。 このDスクリプトの名前はD2.dです:

 pid$target:a.out:foo:4,
 pid$target:a.out:-:40110a
 {
     printf("%x %s:%s\n", uregs[R_PC], probefunc, probename);
 }

Dスクリプトを実行します:

sudo dtrace -c ./a.out -qs D2.d

出力は次のようになります:

 40110a foo:4
 40110a -:40110a

相対オフセットfoo:4と絶対オフセット-:40110aの両方を使用して、選択した命令を調べます。 両方のプローブが起動し、どちらも同じPC 0x40110aを報告します。

pidの安定性

pidプロバイダは、DTraceの安定性メカニズムを使用してその安定性を記述します。 これらの値を次の表に示します。

要素 名前の安定性 データの安定性 依存クラス

プロバイダ

発展中

発展中

ISA

モジュール

非公開

非公開

不明

関数

非公開

非公開

不明

名前

発展中

発展中

ISA

引数

非公開

非公開

不明