CFBundleGetFunctionPointerForName 和 dlsym return 导出函数为 NULL
CFBundleGetFunctionPointerForName and dlsym return NULL for exported function
我有一个 JavaScriptCore 框架的分支,我在其中添加了一个我自己的导出函数。框架编译才发现。框架上的 运行 nm
显示函数 (JSContextCreateBacktrace_unsafe
) 确实已导出:
Leo-Natans-Wix-MPB:JavaScriptCore.framework lnatan$ nm -gU JavaScriptCore.framework/JavaScriptCore | grep JSContextCreateBacktrace
00000000004cb860 T _JSContextCreateBacktrace
00000000004cba10 T _JSContextCreateBacktrace_unsafe
但是,我无法使用 CFBundleGetFunctionPointerForName
或 dlsym
获取该函数的指针; return NULL
。起初,我使用 dlopen
打开我的框架,然后尝试使用 CFBundleCreate
然后 CFBundleGetFunctionPointerForName
但那也是 returns NULL.
什么可能导致这种情况?
更新
发生了一些可疑的事情。我重命名了一个 JSC 函数,nm
反映了这一点。但是,dlsym
仍然能够找到具有原始名称的函数,而不是重命名的函数。
很难追踪到这个问题,因为它高度依赖于您的特定环境和情况,但您很可能 运行 遇到了这个问题,因为系统映像已经加载,而您还没有t 更改了框架的名称。
如果您查看 dyld/dyldAPIS.cpp:1458 中 dlopen
的源代码,您会注意到传递给 dyld 的上下文配置为 matchByInstallName = true
。然后将此上下文传递给 load
,后者执行图像加载所需的各个阶段。有几个阶段值得注意:
loadPhase2
in dyld/dyld.cpp:2896 提取框架路径结尾,在搜索路径中搜索
loadPhase5check
in dyld/dyld:2712 遍历所有加载的图像并确定它们中是否有匹配的安装名称,如果有,它 returns而不是加载一个新的。
loadPhase5load
在 dyld/dyld:2601 最终加载图像,如果它不是 loaded/found 之前的任何步骤。 (值得注意的是 loadPhase5check
首先执行,因为图像加载是一个两次通过的过程。)
考虑到以上所有情况,我会尝试将您的框架重命名为 JavaScriptCore.framework
以外的名称。根据系统框架和您的框架的安装名称,我还建议更改安装名称。 (有大量博客文章和 Whosebug 帖子记录了如何使用 install_name_tool -id
执行此操作。)
我有一个 JavaScriptCore 框架的分支,我在其中添加了一个我自己的导出函数。框架编译才发现。框架上的 运行 nm
显示函数 (JSContextCreateBacktrace_unsafe
) 确实已导出:
Leo-Natans-Wix-MPB:JavaScriptCore.framework lnatan$ nm -gU JavaScriptCore.framework/JavaScriptCore | grep JSContextCreateBacktrace
00000000004cb860 T _JSContextCreateBacktrace
00000000004cba10 T _JSContextCreateBacktrace_unsafe
但是,我无法使用 CFBundleGetFunctionPointerForName
或 dlsym
获取该函数的指针; return NULL
。起初,我使用 dlopen
打开我的框架,然后尝试使用 CFBundleCreate
然后 CFBundleGetFunctionPointerForName
但那也是 returns NULL.
什么可能导致这种情况?
更新
发生了一些可疑的事情。我重命名了一个 JSC 函数,nm
反映了这一点。但是,dlsym
仍然能够找到具有原始名称的函数,而不是重命名的函数。
很难追踪到这个问题,因为它高度依赖于您的特定环境和情况,但您很可能 运行 遇到了这个问题,因为系统映像已经加载,而您还没有t 更改了框架的名称。
如果您查看 dyld/dyldAPIS.cpp:1458 中 dlopen
的源代码,您会注意到传递给 dyld 的上下文配置为 matchByInstallName = true
。然后将此上下文传递给 load
,后者执行图像加载所需的各个阶段。有几个阶段值得注意:
loadPhase2
in dyld/dyld.cpp:2896 提取框架路径结尾,在搜索路径中搜索loadPhase5check
in dyld/dyld:2712 遍历所有加载的图像并确定它们中是否有匹配的安装名称,如果有,它 returns而不是加载一个新的。loadPhase5load
在 dyld/dyld:2601 最终加载图像,如果它不是 loaded/found 之前的任何步骤。 (值得注意的是loadPhase5check
首先执行,因为图像加载是一个两次通过的过程。)
考虑到以上所有情况,我会尝试将您的框架重命名为 JavaScriptCore.framework
以外的名称。根据系统框架和您的框架的安装名称,我还建议更改安装名称。 (有大量博客文章和 Whosebug 帖子记录了如何使用 install_name_tool -id
执行此操作。)