2009-07-29 8 views
5

私のプログラム:DTraceが無効アドレスエラーを発生させる理由は何ですか?

typedef struct objc_class { 
    struct objc_class *isa; 
    struct objc_class *super_class; 
    char *name; 
    long version; 
    long info; 
    long instance_size; 
    void *ivars; 
    void *methodLists; 
    void *cache; 
    void *protocols; 
} *Class; 
struct objc_object { 
    Class isa; 
}; 

/* Code to extract the class name from arg0 based on a snippet by Bill Bumgarner: http://friday.com/bbum/2008/01/26/objective-c-printing-class-name-from-dtrace/ */ 

objc$target:NSObject:-init:entry { 
    printf("time: %llu\n", timestamp); 
    printf("arg0: %p\n", arg0); 
    obj = (struct objc_object *)copyin(arg0, sizeof(struct objc_object)); 
    printf("obj: %p\n", obj); 
    printf("obj->isa: %p\n", obj->isa); 
    isa = (Class)copyin((user_addr_t)obj->isa, sizeof(struct objc_class)); 
    printf("isa: %p\n", obj->isa); 
    classname = copyinstr((user_addr_t)(isa->name)); 
    printf("classname: %s\n", classname); 
} 

いくつかの出力:

dtrace: script 'test.d' matched 1 probe 
dtrace: error on enabled probe ID 1 (ID 61630: objc5936:NSObject:-init:entry): invalid address (0x90206b98) in action #8 at DIF offset 28 
dtrace: error on enabled probe ID 1 (ID 61630: objc5936:NSObject:-init:entry): invalid address (0x90206b98) in action #8 at DIF offset 28 
dtrace: error on enabled probe ID 1 (ID 61630: objc5936:NSObject:-init:entry): invalid address (0x90206b98) in action #8 at DIF offset 28 
CPU  ID     FUNCTION:NAME 
    0 61630      -init:entry time: 28391086668386 
arg0: 1291ae10 
obj: 6f0a1158 
obj->isa: a023f360 
isa: a023f360 
classname: NSBitmapImageRep 

    1 61630      -init:entry time: 28391586872297 
arg0: 12943560 
obj: 6f4a1158 
obj->isa: 2fca0 
isa: 2fca0 
classname: GrowlApplicationTicket 

    1 61630      -init:entry time: 28391586897807 
arg0: 152060 
obj: 6f4a1280 
obj->isa: 2fe20 
isa: 2fe20 
classname: GrowlNotificationTicket 

    2 61630      -init:entry time: 28391079142905 
arg0: 129482d0 
obj: 700a1128 
obj->isa: a0014140 
isa: a0014140 
classname: NSDistributedObjectsStatistics 

    2 61630      -init:entry time: 28391079252640 
arg0: 147840 
obj: 700a1250 
obj->isa: a0014780 
isa: a0014780 
classname: NSDistantObjectTableEntry 

なぜエラー?それはクラス名(それは唯一の%sだと私はそれを削除する場合はエラーが表示されません)が、なぜそれはいくつかのクラスの名前が無効なポインタだと思いますか?

私のDTraceプログラムのどの行が問題を引き起こしたかを実際に教えてくれるエラーメッセージを表示する方法はありますか?

この構造検査ダンスの代わりにobject_getClassNameに電話する方法はありますか?

私はトレースしているプログラムがうまくいけばクラッシュすることはないので、クラスが本当に壊れているとは思わない。

答えて

0

これは、提供された情報に基づく私の推測です。

DTraceは、DTraceスクリプトを可能な限り確定的にするように意図的に設計されています。このため、ifステートメント、ループ、サブルーチン(DTrace自体が提供する擬似サブルーチン以外)などがありません。これは、DTraceスクリプトのコードがカーネルモードで実行されているためです。プロセスがトレースされています。一般的に、DTraceがアクセスできる情報は「ほとんどの一般化のように、「読み取り専用」です(厳密にはそうではありません)、プログラムやカーネル内のビットを揺らすことができ、DTraceほど強力なものが非常に、非常に間違って、非常に非常に迅速に。

ドーナツのドーナツは、ポインタが指すページがVMシステムによってコアにマップされていないため、問題があります。 DTraceは、重複しているVMシステムをページにロードすることはできません。

もしあなたがクラスが何であるべきかを知っていて、必要なものを参照するたくさんのダミーのNSLog()ステートメントを実行することによって、ページをコアにマップさせることができれば、あなたのプログラムの早い段階で、いくつかの便利なところでクラスが始まります。

+0

私はこの最後の夜について考えました。 DTraceの設計は、カーネル内で実行される「コード」の量を最小限に抑え、できるだけ「安全」な状態に保ちます。 シンボル名の解決はカーネルの外側で行われます。カーネルはアドレスをバッファに記録するだけで、外部プログラムはその事実の後で何かが読めるものに変換されます。 アイデアは、なぜ「カーネル外」のアクティビティにObjCクラスの名前解決を追加しないのですか?可能かどうかを調べるために少し調べる価値があるかもしれませんし、アップルにRFEバグレポートを送ってください。 – johne

2

私はこれを完全に追跡していません。 DTraceがいくつかのObjective-Cシンボルを解決しようとしている可能性があります。 DTraceは動的なトレース機能ですが、実行時にObjective-Cが動的にロードするものとうまくマッチしません。 Objective-Cが新しいクラスなどをロードするとき、DTraceはこれを解決しなければならず、特にアプリケーションが起動しているときには少し時間がかかります。物事がロードされても、objcアプリケーションが新しいクラスをobjcランタイムにロードしていても、可能なDTraceは不正な順序でメソッドを表示してしまう可能性があります(正しいオーダーメソッドが実行されていることが気になる場合) 、不正確なタイミング結果などを印刷する。

5

コーリンはかなり近づいています。

参照:

http://www.friday.com/bbum/2008/01/03/objective-c-using-dtrace-to-trace-messages-to-nil/

ない可能性が高い、あなたはavoidDYLD_SHARED_REGION環境変数を設定する必要があります。 dtraceは実際に物理メモリに常駐するマップされたメモリに対してのみ実際に動作します。

vmmapコマンドラインツールを使用すると、欠落しているものを突き止めることができます。

上記のエラーメッセージが生成された後にアプリケーションでvmmap PIDを実行してください。出力を見ると、0x90206b98のようなアドレスがどの地域に入るのかを見ることができます。そのアドレスが与えられれば、おそらく常駐していない書き込み不可能な共有メモリのチャンク内にある可能性が高く、したがってdtraceはそれを読み取ることができません。

3

このエラーは、まだフォールトインしていないページでcopyin/copyinstrが使用された場合に発生します。一般的な回避策は、問題のデータを関数に使用させ、次に::: return節でcopyin [str]を使用させることです。例:

syscall::open:entry 
{ 
    self->filename = arg0; /* Hang on to the file name pointer. */ 
} 

syscall::open:return 
/self->filename/ 
{ 
    @files[copyinstr(self->filename)] = count(); 
    self->filename = 0; 
} 

END 
{ 
    trunc(@files, 5); 
} 
関連する問題