objcメソッドが戻ったときに起動するアクションを作成しました(objc ::: return)。今のところ、戻り値を取得する必要があります。出来ますか?
1 に答える
要約すると、いいえ、DTraceプローブでObjective-Cメソッドの戻り値を取得することはできません。
Bill Bumgarnerは、メッセージをnilにトレースすることについて投稿しており、次のように述べています。
余談です
objc_msgSend()
が、現時点では、dtraceを介してリターンをトレースすることはできません。関数が実際に返されないことを考えると、当然のことです。dtraceに関する限り、これは前文にすぎません。
ブログ投稿はかなり古く(2008年1月)、objcプロバイダーではなくpidプロバイダーを使用しています。とはいえ、Mac OS X v10.7.1の時点でも有効であり、objcプロバイダーにも適用されます。
面白いことに、それは時々機能するように見えるかもしれませんが、DTraceがRAXレジスタを読み取るタイミングによって異なります。が返されないためobjc_msgSend()
、DTraceは、トレースされているメソッドの戻りであるとは限らないコードによって格納されたRAXの値を使用することになります。
次のコードを検討してください。
NSNumber *n = [NSNumber numberWithInt:1234];
printf("n has address %p\n", n);
および次のプローブ:
objc$target:NSPlaceholderNumber:-initWithInt?:return
{
printf("Returning from -[NSPlaceholderNumber initWithInt:]\n");
printf("\treturn value = 0x%p\n", (void *)arg1);
}
DTraceを使用して実行すると、次の出力が得られます。
n has address 0x4d283
Returning from -[NSPlaceholderNumber initWithInt:]
return value = 0x4d283
したがって、プローブはの戻り値をキャプチャできたようです-initWithInt:
。ただし、これは運だけです。おそらく、によって呼び出され、期待値をRAXに配置する関数(CFNumberCreate()
または)が原因である可能性があります。CFMakeCollectable()
-initWithInt:
ここで、次のコードについて考えてみます。
char *c = "hello";
NSData *data = [NSData dataWithBytes:c length:strlen(c)];
NSString *s = [[NSString alloc] initWithData:data
encoding:NSASCIIStringEncoding];
printf("s has address %p\n", s);
および次のプローブ:
objc$target:NSPlaceholderString:-initWithData?encoding?:return
{
printf("Returning from -[NSPlaceholderString initWithData:encoding:]\n");
printf("\treturn value = 0x%p\n", (void *)arg1);
}
DTraceを使用して実行すると、次の出力が得られます。
s has address 0x7fcd92414ea0
Returning from -[NSPlaceholderString initWithData:encoding:]
return value = 0x600
ご覧のとおり、アドレス(つまり戻り値)が一致していません。実際、0x600は、のCoreFoundationのkCFStringEncodingASCII
対応物である値ですNSASCIIStringEncoding
。ある時点で、メソッドまたはメソッドによって呼び出された関数のいずれかが0x600をRAXに移動しました。これは、DTraceが誤って戻り値と見なした値です。