linux – 为什么链接器修改–defsym“绝对地址”
目标:使用可执行文件中的函数(不导出符号)的共享库.
意思是:gcc -Wl,– defsym,function = 0x432238 该手册页指出: "--defsym symbol=expression" Create a global symbol in the output file,containing the absolute address given by expression. 令我沮丧的是,dlopen()将0x7ffff676f000,共享库的基地址(这是64位代码)添加到导出的“绝对符号地址”: executable shared library ---------- linker -------------- symbol: 0x432238 =====> 0x7ffff6ba1238 objdump在库中显示正确的符号地址(0x432238),但一旦加载了dlopen(),该符号的地址为0x7ffff6ba1238. 如果,一旦加载,我手动将库符号修补到正确的地址,然后一切正常(否则,库SEGFAULTs). >为什么修改“绝对地址”? 更新: 我对以下答复的技术相关性提出质疑,并且更多的是“更新”: 使用–defsym在PIC库/可执行文件中定义重定位符号是没有意义的(除了在没有任何可用功能的情况下污染二进制文件之外,它不起任何作用). 因此,PIC共享库或PIC可执行文件中–defsym的唯一相关用法应该是定义(非重定位)“绝对地址”. 顺便说一句,如果您懒得阅读手册页,这是–defsym的官方目的: “在输出文件中创建一个全局符号,包含表达式给出的绝对地址.” 充其量,这是一个Linux链接器的影响,这将是微不足道的修复.对于那些不能等待拒绝人员实现(并修复)他们的错误的人来说,解决方案是在缺陷链接器加载二进制映像之后修补重定位表. 然后,-defsym在PIC库/可执行文件中变得很有用,在我看来这是一个值得欢迎的进展. 解决方法
你似乎从根本上误解了–defsym的作用.
--defsym=symbol=expression Create a global symbol in the *output* file,... 也就是说,您正在构建的库中创建新符号.因此,符号(自然地)与库重新定位. 我猜你想要这样的东西: // code in library int fn() { // exe_fn not exported from the executable,but we know where it is. int (*exe_fn)(void) = (int (*)(void)) 0x432238; return (*exe_fn)(); } 如果您不想将0x432238硬编码到库中,而是在构建时在命令行上传递值,只需使用-DEXE_FN = 0x432238即可实现. 更新:
您选择的方法无法实现这一目标.你必须使用其他方法.
事实并非如此.当您要求链接器在绝对地址0x432238处定义函数时,它就是这样做的.你可以在objdump,nm和readelf -s输出中看到它. 但是因为符号是在共享库中定义的,所以对该符号的所有引用都被重定位,即通过共享库加载地址(由动态加载器完成)进行调整.对于动态加载器来说,没有任何意义.
你不能.使用其他方法来实现您的目标. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |