更新
在与 OP 澄清 __TEXT.__objc_methname 的扩展将在现有可执行文件的 Mach-O 后处理期间发生后,我对这个问题有了新的认识。
另一种方法是创建一个新的加载命令LC_SEGMENT_64 和一个新的__TEXT_EXEC.__objc_methname 段/节条目(通常__TEXT_EXEC 用于一些内核内容,但本质上它与__TEXT 相同)。这里有一个快速 POC 来说明这个概念:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
printf("%lx",[NSObject new]);
}
return 0;
}
像这样编译:
gcc main.m -c -o main.o
ld main.o -rename_section __TEXT __objc_methname __TEXT_EXEC __objc_methname -lobjc -lc
有趣的是,只有直到 High Sierra 10.14.6 的 ld 会生成 __TEXT.__objc_methname,在 Catalina 上没有任何痕迹,它的做法不同。
UPDATE2。
玩弄它,我注意到__TEXT 段(和__TEXT_EXEC 就此而言)的执行权不需要__objc_methname 工作。
甚至不需要更好的特定段和部分名称:
我可以成功:
__DATA.__objc_methname
__DATA_CONST.__objc_methname
__ARBITRARY.__arbitrary
或者在我的情况下是最后一个__DATA 部分
__DATA.__objc_classrefs,其中原始数据由选择器名称连接。
只要存在带有选择器名称的正确的以空结尾的 C 字符串,一切都很好。如果我故意在十六进制编辑器或 MachOView 中破坏“new\0”,我会得到 p>
"+[NSObject ne]: unrecognized selector sent to instance ..."
在启动我的 POC 可执行文件时,肯定会使用该值。
总而言之,__TEXT.__objc_methname 部分本身可能是链接器提供的一些调试器提示。应用程序运行时似乎只需要在内存中的任何位置将选择器名称命名为char*。