2013-10-27 23 views
2

我正在尝试编写一个DTrace脚本,它将向我显示传递给-[NSURLConnection sendSynchronousRequest:returningResponse:error:]的参数,并且我找不到一个用于从传入的字符串中提取字符串的结构NSString参数。这question有一个适用于OS X应用程序的答案,但它不适用于我使用iOS模拟器的应用程序。定义用于Objective-C对象的DTrace兼容结构

尽管我正在寻找这个特定示例的解决方案,但我更感兴趣的是学习定义/发现任何给定Objective-C对象的基础内存结构的最佳方法。正如您从我写的OS X测试应用程序中可以看到的,NSString参数并不总是将原始字符串数据放在同一个地方。在__NSCFString似乎位于16字节英寸的位置(长度前缀)的情况下。如果是__NSCFConstant字符串,则它在其他地方看起来并不明显,看着原始内存转储。

如果在系统头文件中定义了结构体,它会告诉我我在找什么,那将是第一步,但我认为LLDB应该能够向我展示有用的提示。

NSString Memory Dump Comparison

回答

1

从理论上讲,Class-dump应该能够观察一个Mach-O的文件,并为您的目标C类报告的声明。

当我上次尝试使用Class-dump时,我没有任何成功;我不记得确切的原因,但我现在看到有一种可能的选择,即Hopper。无论如何,在阅读文章Abusing the Objective C runtime之后,我用gdb来检查地址空间;与您不同,我使用DTrace停止进入方法的过程,然后检查arg2寻址的内存。如果在你的情况下,你看不到一个合理的字符串,那么我建议你寻找指针并遵循它们。

请注意,您的问题使用短语“DTrace兼容”。这提出了一个有趣的观点:dtrace(1)是一个编译器,它不必像构建受害者时那样使用相同的方式打包结构。在Solaris上,dtrace(1)符合给定平台的ABI,无论是SPARC还是x86。我没有调查过它在MacOS上的行为,但它可能会有所不同,所以请记住这一点,特别是如果dtrace给您带来意想不到的结果。

1

只要符合Objective C运行时的公共定义,编译器就可以使用ObjC代码创建几乎所有的东西。

我认为你选择了错误的对象来开始你的学习:NSString(和NSNumber一起)有多个版本,根据你的使用情况选择。例如。你的编译时间常数的NSString很可能表现为:

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

您也可以通过检查__cfstring段,例如找到你不变的NSString(或CFString字符串)通过otool otool -s __DATA __cfstring

我不知道任何方法可以让你反编译任何ObjC对象到C-struct形式。我的建议是通过反汇编程序来查看各个对象的字段是如何访问的。例如。你可以给你的属性的setter和getters添加断点。

如果你感觉很舒服,你还可以学习负责制定高水平的代码转换成中间(基于LLVM编译器的情况下)表示编译器的源代码:CGObjCMacCGObjCCGObjCRuntime