BTK*_*BTK 9 objective-c objective-c-runtime ios method-swizzling
我基本上正在寻找一种方法来检测何时/什么第三方库调配.我最近遇到了一个广告库使用了AFNetworking的古怪分叉的情况.AFNetworking对NSURLSessionTask进行了调整,在某些情况下,这两个混合体并没有很好地发挥作用.我真的希望能够检测和理智检查这种事情,理想情况下甚至在应用程序中保留每个混合方法的版本化转储,这样我们就可以了解谁在修补什么以及风险是什么.谷歌和堆栈溢出搜索只发布了一堆关于如何调整的教程.有人遇到过这个问题或有解决方案吗?看起来我可能能够使用objc/runtime.h编写代码,但我无法想象我是第一个需要它的人.
这是我能够得到的最接近的,经过几个小时的修补.它涉及使用mach_override的一个分支,关于加载顺序的几个DYLD怪癖,以及疯狂黑客的胃.
它只能在模拟器上运行,但这应该足以满足您的用例(我当然希望您没有依赖于设备的依赖项).
代码的内容看起来像这样:
#include <objc/runtime.h>
#include <mach_override/mach_override.h>
// It is extremely important that we have DYLD run this constructor as soon as the binary loads. If we were to hook
// this at any other point (for example, another category on NSObject, in the main application), what could potentially
// happen is other `+load` implementations get invoked before we have a chance to hook `method_exchangeImplementation`,
// and we don't get to see those swizzles.
// It is also extremely important that this exists inside its own dylib, which will be loaded by DYLD before _main() is
// initialized. You must also make sure that this gets loaded BEFORE any other userland dylibs, which can be enforced by
// looking at the order of the 'link binary with libraries' phase.
__attribute__((constructor))
static void _hook_objc_runtime() {
kern_return_t err;
MACH_OVERRIDE(void, method_exchangeImplementations, (Method m1, Method m2), &err) {
printf("Exchanging implementations for method %s and %s.\n", sel_getName(method_getName(m1)), sel_getName(method_getName(m2)));
method_exchangeImplementations_reenter(m1, m2);
}
END_MACH_OVERRIDE(method_exchangeImplementations);
MACH_OVERRIDE(void, method_setImplementation, (Method method, IMP imp), &err) {
printf("Setting new implementation for method %s.\n", sel_getName(method_getName(method)));
method_setImplementation_reenter(method, imp);
}
END_MACH_OVERRIDE(method_setImplementation);
}
Run Code Online (Sandbox Code Playgroud)
这非常简单,并产生如下输出:
交换方法描述和custom_description的实现.
没有好的方法(没有使用断点并查看堆栈跟踪)来确定哪个类正在调整,但对于大多数情况,只要看看选择器应该给你一个关于从那里去哪里的提示.
它似乎适用于我创建的几个类别,在+load
我阅读mach_override
和DYLD的内部结构中,只要您正确设置了库加载顺序,您可以期望在任何其他用户之前初始化它-land代码,如果你把它放在它自己的动态库中.
现在,我无法保证这一点的安全性,但作为一个调试工具保持不变似乎很有用,所以我将我的例子发布到github:
https://github.com/richardjrossiii/mach_override_example
这是麻省理工学院的许可,所以请随意使用.
归档时间: |
|
查看次数: |
1256 次 |
最近记录: |