我们有一个插件系统,它通过 dlopening/LoadLibrarying dll/so/dylib 然后 dlsyming/GetProcAddressing 函数调用 dll(用户生成的插件)中的函数,然后将结果存储在函数指针中。
不幸的是,由于复制粘贴了一些错误的示例代码,这些 dll 中的一些没有正确的函数签名,并且不包含 return 语句。
一个 dll 可能包含以下内容:
extern "C" void Foo() { stuffWithNoReturn(); } // copy-paste from bad code
或者它可能包含以下内容:
extern "C" int Foo() { doStuff(); return 1; } // good code
加载 dll 的应用程序依赖于返回值,但是有大量没有返回语句的 dll。我正在尝试检测这种情况,并警告用户他的插件存在问题。
这个天真的代码应该解释我想要做什么:
typedef int (*Foo_f)(void);
Foo_f func = (Foo_f)getFromDll(); // does dlsym or GetProcAddress depending on platform
int canary = 0x42424242;
canary = (*func)();
if (canary == 0x42424242)
printf("You idiot, this is the wrong signature!!!\n");
else
real_return_value = canary;
不幸的是,这不起作用,金丝雀在调用具有已知缺陷的 dll 后包含一个随机值。我天真地假设调用一个没有返回语句的函数会使金丝雀完好无损,但事实并非如此。
我的下一个想法是编写一点内联汇编程序来调用该函数,并在返回时检查 eax 寄存器,但 Visual Studio 2015 不再允许在 x64 代码中使用 __asm()。
我知道没有符合标准的解决方案,因为将函数指针转换为错误的类型当然是未定义的行为。但是,如果有人有一个至少可以在 64 位 Windows 上使用 Visual C++ 的解决方案,或者一个可以在 MacOS 上使用 clang 的解决方案,我会非常高兴。