某些特定于平台的功能(如SSE或AVX)的可用性可以在运行时确定,如果不想为不同的功能编译和发送不同的对象,这非常有用.
例如,下面的代码允许我检查AVX并使用gcc编译,它提供了cpuid.h标题:
#include "stdbool.h"
#include "cpuid.h"
bool has_avx(void)
{
uint32_t eax, ebx, ecx, edx;
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
return ecx & bit_AVX;
}
Run Code Online (Sandbox Code Playgroud)
通过运行时检查(如上所述)重复执行检查而不是乱丢代码,而不是引入分支(可以缓存检查以减少开销,但仍会有分支),我想我可以使用动态链接器/加载器提供的基础结构.
在具有ELF的平台上调用具有外部链接的功能已经是间接的,并通过程序链接表/ PLT和全局偏移表/ GOT.
假设有两个内部函数,一个基本的_do_something_basic,总是以某种方式优化的版本_do_something_avx,它使用AVX.我可以导出一个通用do_something符号,并将其别名为基本添加:
static void _do_something_basic(…) {
// Basic implementation
}
static void _do_something_avx(…) {
// Optimized implementation using AVX
}
void do_something(…) __attribute__((alias("_do_something_basic")));
Run Code Online (Sandbox Code Playgroud)
在我的库或程序的加载时间内,我想检查一次使用AVX的可用性,has_avx并根据do_something符号的检查点的结果_do_something_avx.
如果我能将do_something符号的初始版本指向一个自我修改函数来检查AVX的可用性has_avx并将其替换为_do_something_basic或更好,那就更好了_do_something_avx.
理论上这应该是可能的,但是如何以编程方式找到PLT/GOT的位置?是否有一个ABI/API提供ELF加载器,例如ld-linux.so.2,我可以用它吗?我是否需要链接描述文件来获取PLT/GOT位置?如果我获得指向它的指针,我甚至可以写入PLT/GOT安全考虑因素?
也许有些项目已经完成了这个或者已经非常相似的事情
我完全清楚,解决方案将是高度特定于平台的,但由于我已经不得不处理低级平台特定的细节,例如指令集的功能,这很好.