如何静态转储在Cocoa应用程序中调用的所有ObjC方法?

6
假设我有一个基于Cocoa的Mac或iOS应用程序。我想在我的应用程序源代码或应用程序二进制文件上运行静态分析器,以检索其中调用的所有Objective-C方法列表。是否有这样的工具?
几点说明:
我正在寻找一种静态解决方案。我不需要动态解决方案
可以针对二进制或源代码运行的东西是可接受的。
理想情况下,输出将只是一个巨大的去重的Objective-C方法列表,例如: ... -[MyClass foo] ... +[NSMutableString stringWithCapacity:] ... -[NSString length] ...
(如果没有去重,那也没关系)
如果存在其他类型的符号(C函数、静态变量等),那也没问题。
我熟悉class-dump,但据我所知,它会在你的二进制文件中转储声明的类,而不是调用的方法。这不是我要找的。如果我错了,而且你可以用class-dump做到这一点,请纠正我。
我不确定这是否可行。如果不行,那也是一个好答案。 :)
4个回答

10

我所了解的最接近的工具是otx,它是otool的包装器,可以在objc_msgSend()调用点重构选择器。

http://otx.osxninja.com/


1
该域名已不存在。请从archive.org中访问http://web.archive.org/web/20130929164302/http://otx.osxninja.com/。 - Klaas

7
如果您要查找所有方法的完整列表,无论是静态还是动态,这都是不可能的。原因是方法可以以各种方式调用,甚至可以在运行时和程序中动态组装。
除了使用Objective-C消息(如[Object message])进行常规方法调用之外,您还可以使用来自objc/message.h的C-API函数分派消息,例如objc_msgSend(str, del)。或者您可以使用NSInvocation API或performSelector:withObject:(以及类似的方法),请参见此处的示例。在所有这些情况下使用的选择器可以是静态字符串,也可以从字符串动态构造,使用像NSSelectorFromString这样的东西。
更糟糕的是,Objective-C甚至支持动态消息解析,允许对象响应根本不对应于方法的消息!
如果您仅满足于特定方法的调用,则解析上述模式的源代码将为您提供可能在执行期间调用的最小方法列表。但是,该列表可能既不完整(即不包含可能被调用的方法),也可能过度完整(即可能包含实际上未被调用的方法)。

我非常喜欢这个答案。你提出了一个非常重要的观点:由于你提到的ObjC运行时/语言特性,没有静态解决方案可以保证100%的覆盖率。然而,我认为即使如此,我的问题仍然有价值,因为可以找到其他部分的工具。 - Todd Ditchendorf
3
我认为比元编程的怪异性更大的问题是在编译时不知道接收者的类型,这是确定调用哪个方法必须知道的。当我写[foo length]时,你不知道它是-[NSString length]-[FootballField length]还是+[SomePoorlyDesignedClass length]——在运行时可能是这三者的任意组合,甚至是从插件加载的其他方法。因此,您可以相当准确地确定发送了哪些消息,但尝试说出由此调用了哪些方法就更加靠不住了。 - Chuck
@Chuck 说得好。不仅是选择器,还有对象本身也可以动态构建。+1 还要指出实例方法和类方法方面的微妙之处! - user8472

1
otool -oV /path to executable/ | grep name | awk '{print $3}'

0
另一个很棒的工具是class-dump,它一直是我进行静态分析的首选之一。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接