我最近发现,您可以在运行时将机器代码注入缓冲区中,将其强制转换为函数指针,然后调用它以执行缓冲区中的指令。看起来像这样:
int main(void)
{
char buffer[] = "\xB8\x04\x00\x00\x00\xC3";
auto func = (int(*)())buffer;
func();
return 0;
}
现在,如果我不想在运行时为函数调用付费,换句话说,我想将缓冲区视为inline
函数。
我为达到这一目的的首次尝试是将buffer
和func
都声明为constexpr
,并用static_cast
替换c样式强制转换。似乎不起作用,因为根据gcc,这是无效的转换。
也尝试过reinterpret_cast
,但显然无法在编译时进行评估
任何想法都将受到欢迎,如果可以实现的话。
答案 0 :(得分:2)
可以使用asm declaration将内联汇编代码插入C ++函数中。有条件地支持此构造并定义实现。
在大多数实现中,asm声明需要某种形式的符号汇编语言,而不是二进制目标代码。
这是在x86上使用asm
声明结构和GCC的示例。
#include <iostream>
template <int nontype>
int add(int operand)
{
int sum;
asm ("movl %1, %0\n\t"
"addl %2, %0"
: "=r" (sum)
: "r" (operand), "r" (nontype)
: "0");
return sum;
}
int main()
{
std::cout << add<42>(6) << "\n";
}
这将按预期打印48。
请注意,gcc的asm
版本非常强大,其语法必须超出该标准指定的语法才能支持其许多功能。其他实现可能会或可能不会提供这样的灵活性(或实际上根本不提供任何东西-该结构受条件支持)。
在函数指针和数据指针之间进行转换是C ++中未定义的行为。实现可以用它们做任何他们想做的事情。我猜想,对于大多数实施者的任务清单来说,利用这种特殊形式的UB复制完美的asm声明功能将是相当低的。