1

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.

Community
  • 1
  • 1
ericg
  • 8,413
  • 9
  • 43
  • 77
  • It would be much easier to use USDT rather than hacking NSString internal representation. – Kentzo Mar 21 '13 at 14:49
  • Perhaps, but the question remains. Furthermore, there are potentially a lot of methods to which I would need to add a USDT and when all is said and done, given the degree to which I have littered my code with debug code and the amount of work to add all of the USDTs, having the ability to simply print a NSString could very well be the easiest thing to do. – ericg Mar 22 '13 at 02:48

1 Answers1

2

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.

Robert Harris
  • 1,522
  • 9
  • 11
  • This solution works for OS X apps, but doesn't seem to work for iOS apps running under the Sim. Presumably the struct for NSString is a bit different. Can you elaborate on how you came up with the struct using gdb? – Mark Edington Oct 26 '13 at 23:22
  • @MarkEdington: see [my answer](http://stackoverflow.com/questions/19622839/define-dtrace-compatible-structs-for-objective-c-objects/19662008#19662008) to your formal question. – Robert Harris Oct 29 '13 at 15:17