Define DTrace Compatible Structures for Objective-C Objects

I am trying to write a DTrace script that will show me the parameter passed in -[NSURLConnection sendSynchronousRequest:returningResponse:error:] , and I cannot find a structure that works to extract the string from the passed NSString parameter. This question has an answer that works for OS X applications, but it doesnโ€™t work for my application that uses the iOS simulator.

Although I am looking for a solution for this specific example, I am much more interested in finding out the best way to determine / discover the underlying memory structure for any given Objective-C object. As you can see from the OS X test application that I wrote, the NSString parameter does not always contain the original string data in the same place. In the case where it __NSCFString seems to be located (prefix length) with 16 bytes in. In the case when he a __NSCFConstant builds it somewhere else, which is not immediately obvious, looking at a dump of raw memory.

If there are structures in the system headers that show me what I'm looking for, that would be a good first step, but I think LLDB can also show me useful hints.

NSString Memory Dump Comparison

+2
struct objective-c lldb dtrace
source share
2 answers

In theory, Class-dump should be able to examine the Mach-O file and report declarations for Objective-C classes.

When I last tried to use Class-dump, I had no success; I donโ€™t remember exactly why, but now I see that there is a possible alternative, namely Hopper . Anyway, after reading the Objective-C runtime violation article, I used gdb to check the address space; unlike you, I used DTrace to stop the process when I entered the method, and then examined the memory addressed by arg2. If in your case you do not see a reasonable line, I suggest you look for pointers and follow them.

Please note that the phrase "DTrace-compatible" is used in your question. This raises an interesting point: dtrace (1) is a compiler, and it is not required to pack structures in the same way as everything that was used to create your victim. On Solaris, dtrace (1) corresponds to the ABI of the platform, whether it be SPARC or x86. I have not investigated its behavior on MacOS, but it may be different, so keep that in mind, especially if dtrace gives unexpected results.

+1
source share

The compiler can do almost anything with ObjC code if it matches the publicly available runtime definition c.

I think that you have chosen the wrong object to start your research: NSString (along with NSNumber) has several versions that are selected depending on your use. For example. your NSString compile time constant is most likely represented as:

 struct __builtin_NSString { const int *isa; // point to __NSConstantStringClassReference const char *str; // point to some byte array under __cfstring segment unsigned int length; // size of that byte array }; 

You can also find your constant NSString (or CFString) by checking the __cfstring segment, for example. via otool otool -s __DATA __cfstring .

I do not know of any method that would allow you to decompile any ObjC object into a C-struct form. My suggestion is to see how various areas of objects are accessed by disassembling your program. For example. you can add a breakpoint to the setters and recipients of your properties.

If you feel comfortable, you can also study the source code of the compiler responsible for creating high-level code in the intermediate (in the case of the LLVM-based compiler): CGObjCMac , CGObjC , CGObjCRuntime .

+1
source share

All Articles