13

是否有任何非异国情调的架构/操作系统/编译器发生以下变化:

void func(void *, int, int)

至:

int func(void *, int, int)

会破坏ABI吗?(即为共享库的“void”版本编译的程序在使用“int”版本运行时会中断)

4

1 回答 1

10

有几条评论说不,我们可以通过一点推理来加强这一点。void func(void *, int, int)在最熟悉的 ABI 中,允许带有声明的函数使用int作为临时寄存器返回结果的寄存器;它不需要保存和恢复它。需要带有声明的函数int func(void *, int, int)才能使用int返回结果的寄存器。在其他方面,这些声明是相同的。因此,任何实现的int func(void *, int, int)机器码也是满足的机器码void func(void *, int, int)

换句话说,调用者无法区分故意在返回寄存器中返回结果的机器代码和恰好在该寄存器中留下一些临时计算的代码。

请注意,这种推理要求被调用的函数隐藏在 ABI 后面;它依赖于 ABI 指定的二进制行为。如果被调用函数的源代码在被调用函数被编译时是可见的(或者可能影响调用如何实现的其他部分),那么优化可能会导致绕过 ABI 的行为(例如,观察被调用例程不使用返回寄存器,因此在调用者中使用它来保存一些预期在调用过程中保持不变的值)。

既然你说这是一个共享库,你可能是安全的:共享库是单独编译的,它的源代码对它的调用者不可用。但是,您应该考虑侧通道。例如,共享库可能是一组共享源并包含跨库调用的库的一部分。在这种情况下,某人可能有一个旧版本的共享库,它是在编译时考虑到void源代码的,而新版本的共享库则包含int源代码。(甚至这需要不寻常的源代码安排或将信息集成到多个编译单元的花哨的编译器。)

于 2013-03-26T02:18:29.197 回答