ericg
ericg

Reputation: 8722

How to print a NSString from a DTrace script

This question is asking the same thing, but when I tried:

typedef long long ptr_t;


objc$target:NSWindow:-setTitle?:entry
{

    printf( "%30s %10s %x %x %x\n", probemod, probefunc, arg0, arg1, arg2 );

    this->str = *(ptr_t*)copyin(arg2+2*sizeof(ptr_t), sizeof(ptr_t));

    printf("string addr = %p\n", this->str);
    printf("string val  = %s\n", copyinstr(this->str));
}

It didn't work. arg2 should be the address of the NSString. I got:

NSWindow -setTitle: 100685240 7fff92d82f73 7fff78a6eb80 string addr = 7fff8e7e83b9 string val=Window dtrace: error on enabled probe ID 5 (ID 35737: objc9434:NSWindow:-setTitle::entry): invalid address (0x6c007400690074) in action #8 at DIF offset 24

You can assuming a MacRoman or ASCII encoding of the NSString - basically no need to worry about complicated (from the DTrace perspective) encodings.

Upvotes: 1

Views: 661

Answers (1)

Robert Harris
Robert Harris

Reputation: 1562

Whether or not your question really is the same as the other one depends on whether or not the internal representation of an NSString is the same as that of a CFStringRef. I don't know, and I hope that someone else can clarify, but I suspect that the answer is that the two are different. The D script in the other question's answer implies that a CFStringRef has a character pointer, but playing around with gdb suggests that an NSString looks like this:

struct NSString {
    uintptr_t pad[2];
    char name[1];       /* variable length array */
};

Here's a corresponding script in action:

bash-3.2# cat title.d 
typedef struct {
    uintptr_t pad[2];
    char name[1];
} NSString_t;

objc$target:NSWindow:-setTitle?:entry
{
    self->namep = (uintptr_t)arg2 + offsetof(NSString_t, name);
    printf("name = %s\n", copyinstr(self->namep));

}
bash-3.2# ps -ef | fgrep -i firefox
  501 31895   204   0   0:01.22 ??         0:04.48 /opt/Applications/Firefox.app/Contents/MacOS/firefox -psn_0_27167207
    0 32045 31422   0   0:00.05 ttys000    0:00.06 fgrep -i firefox
bash-3.2# dtrace -arch x86_64 -Cqs title.d -p 31895
name = Mozilla Firefox
name = New Tab
name = New Tab
name = Mozilla Firefox
name = New Tab
^C

bash-3.2#

If you're inspecting a 32-bit process then use -arch i386 and dtrace(1) will adjust its notion of pointer sizes appropriately.

Upvotes: 2

Related Questions