开发者

Is it possible to get the result of objc method in dtrace?

开发者 https://www.devze.com 2023-03-28 00:40 出处:网络
I wrote an action that fires when any开发者_如何学C objc method return (objc:::return). For now, I need to get the return value. Is it possible?In summary: no, you can’t get the return value of an Ob

I wrote an action that fires when any开发者_如何学C objc method return (objc:::return). For now, I need to get the return value. Is it possible?


In summary: no, you can’t get the return value of an Objective-C method in a DTrace probe.

Bill Bumgarner has a post on tracing messages to nil in which he says the following:

Aside: objc_msgSend()‘s return cannot be traced via dtrace at this time. Not surprising given that the function doesn’t actually return — as far as dtrace is concerned, it is nothing but preamble.

The blog post is rather old (January 2008) and it uses the pid provider, not the objc provider. That said, it is still valid as of Mac OS X v10.7.1 and it also applies to the objc provider.

Amusingly, it might seem that it sometimes works but it depends on when DTrace reads the RAX register. Since objc_msgSend() doesn’t return, DTrace ends up using values in RAX that have been stored by code that is not necessarily the return of the method being traced.

Consider the following code:

NSNumber *n = [NSNumber numberWithInt:1234];
printf("n has address %p\n", n);

and the following probe:

objc$target:NSPlaceholderNumber:-initWithInt?:return
{
    printf("Returning from -[NSPlaceholderNumber initWithInt:]\n");
    printf("\treturn value = 0x%p\n", (void *)arg1);
}

When run using DTrace, I get the following output:

n has address 0x4d283
Returning from -[NSPlaceholderNumber initWithInt:]
    return value = 0x4d283

so it seems that the probe was able to capture the return value of -initWithInt:. That’s only luck though, probably caused by a function (e.g. CFNumberCreate() or CFMakeCollectable()) called by -initWithInt: and which ended up placing the expected value in RAX.

Now consider the following code:

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);

and the following probe:

objc$target:NSPlaceholderString:-initWithData?encoding?:return
{
    printf("Returning from -[NSPlaceholderString initWithData:encoding:]\n");
    printf("\treturn value = 0x%p\n", (void *)arg1);
}

When run using DTrace, I get the following output:

s has address 0x7fcd92414ea0
Returning from -[NSPlaceholderString initWithData:encoding:]
    return value = 0x600

As you can see, the addresses (i.e., the return values) don’t match. In fact, 0x600 is the value of kCFStringEncodingASCII which is the Core Foundation counterpart of NSASCIIStringEncoding. At some point either the method or a function called by the method moved 0x600 to RAX and that’s the value that DTrace wrongly considered to be the return value.

0

精彩评论

暂无评论...
验证码 换一张
取 消