2

我正在尝试编写一个 DTrace 脚本,该脚本将向我显示传递给的参数-[NSURLConnection sendSynchronousRequest:returningResponse:error:],但我找不到可用于从传入NSString参数中提取字符串的结构。这个问题的答案适用于 OS X 应用程序,但不适用于我使用 iOS 模拟器的应用程序。

尽管我正在寻找这个特定示例的解决方案,但我更感兴趣的是学习为任何给定的 Objective-C 对象定义/发现底层内存结构的最佳方法。从我编写的 OS X 测试应用程序中可以看出,NSString参数并不总是在同一个地方包含原始字符串数据。如果它的__NSCFString位置(长度前缀)位于 16 字节中。如果它是一个__NSCFConstant字符串,它位于其他地方,在查看原始内存转储时不会立即明显。

如果系统标头中定义了结构,可以向我展示我正在寻找的内容,那将是很好的第一步,但我认为 LLDB 也应该能够向我展示有用的提示。

NSString 内存转储比较

4

2 回答 2

1

只要符合目标 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 形式。我的建议是通过反汇编程序来查看对象的各个字段是如何访问的。例如,您可以向属性的设置器和获取器添加断点。

如果您觉得舒服,您还可以研究负责将高级代码转换为中间(在基于 LLVM 的编译器的情况下)表示的编译器的源代码:CGObjCMacCGObjCCGObjCRuntime

于 2013-10-29T19:46:01.837 回答
1

理论上,Class-dump应该能够检查 Mach-O 文件并报告您的 Objective C 类的声明。

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

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

于 2013-10-29T15:08:56.443 回答