在对外部库的函数调用期间未保存硬件寄存器值R15

问题描述

我的代码用C ++编写,并使用gcc版本4.7.2进行编译。 它与用C编写并使用gcc 4.5.2编译的3rd party库链接。 我的代码调用了一个函数initStuff()。在调试期间,我发现在调用initStuff()之前,R15寄存器的值与从该函数返回时的值不同。 作为一个快速的技巧,我做到了:

asm(" mov %%r15,%0" : "=r" ( saveR15 ) );
initStuff();
asm(" mov %0,%%r15;" : : "r" (saveR15) );

这似乎暂时有效。 这是谁的责任?如何找到是编译器问题还是兼容性问题?

解决方法

x86-64上的

gcc紧跟System V ABI,后者将r15定义为被调用者保存的寄存器;使用该寄存器的任何功能都应该保存和恢复。

因此,如果此第三方功能未执行此操作,则说明它不符合ABI,除非对此进行记录,否则应归咎于此。 AFAIK ABI的这一部分一直稳定,因此,如果编译器生成的代码(带有默认选项)无法保存和恢复r15,则可能是编译器错误。第三方代码的某些部分更有可能使用汇编语言并且存在错误,或者可以想象它是使用非标准编译器选项构建的。

您可以深入研究它,或者作为一种变通办法,在它周围编写包装程序以保存和恢复r15。您当前的解决方法并不十分安全,因为编译器可能会根据周围的代码对asm语句重新排序。您应该改为通过保存并恢复(将其声明为破坏所有调用者保存的寄存器),将对initStuff的调用放在单个asm块中,或者编写一个“裸”程序集包装程序来执行保存/恢复然后呼叫,然后呼叫它。 (请确保保留堆栈对齐。)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...