如何让动态链接器调用自定义函数而非其他共享库中的对应函数
解决方案
可行性结论
完全可以实现,这是Linux动态链接器符号抢占机制的典型适用场景:动态链接器解析符号时,会优先选择最先加载的程序映像中的同名符号,只要将你自行实现的Ini_Conf_Get_Field_Int函数导出到主程序的动态符号表中,后续dlopen加载的闭源库调用该函数时就会优先调用你实现的版本。
报错原因
你遇到的编译报错是因为所用的GNU ld 2.34版本不支持--export-dynamic-symbol选项,该选项是GNU Binutils 2.35版本才新增的功能,老版本ld无法识别该参数,才会出现参数解析错误提示。
兼容旧版本ld的替代方案
方案1:全量导出主程序动态符号(简单易用)
直接使用所有版本ld都支持的-rdynamic参数(等价于-Wl,--export-dynamic),将主程序所有全局符号导出到动态符号表:
cc -o qnap-ec qnap-ec-helper.c -Wall -O2 -ldl -rdynamic
该方案操作简单,普通开发场景下没有额外负面影响。
方案2:仅导出指定符号(更干净)
如果不想导出主程序的所有全局符号,可以通过版本脚本实现仅导出Ini_Conf_Get_Field_Int单个符号:
- 新建符号控制脚本
symbol.map,内容如下:
{ global: Ini_Conf_Get_Field_Int; local: *; };
- 编译时指定版本脚本:
cc -o qnap-ec qnap-ec-helper.c -Wall -O2 -ldl -Wl,--version-script=symbol.map
注意事项
- 你自定义实现的
Ini_Conf_Get_Field_Int函数的签名必须和原库中该函数的签名完全一致,包括返回值类型、参数数量、参数类型、调用约定,否则会触发栈损坏、返回值异常等未定义行为。 dlopen加载闭源库时不要指定RTLD_DEEPBINDflag,该flag会让库优先解析自身内部的符号,会破坏符号抢占逻辑,你当前使用的RTLD_LAZY符合要求。
内容的提问来源于stack exchange,提问作者Harry Muscle
相关产品推荐
相关产品推荐

