我正在使用Linux上的函数指针并尝试执行此C程序:
#include#include int myfun() { return 42; } int main() { char data[500]; memcpy(data, myfun, sizeof(data)); int (*fun_pointer)() = (void*)data; printf("%d\n", fun_pointer()); return 0; }
不幸的是它会fun_pointer()
随叫随到.我怀疑它与一些内存标志有关,但我没有找到有关它的信息.
你能解释为什么这段代码会出现错误吗?没有看到固定的data
数组大小,没有调用函数的复制是正常的.
UPD:最后我发现应该使用带有flag的mprotect系统调用将内存段标记为可执行文件PROT_EXEC
.此外,内存段应由mmap函数返回,如POSIX规范中所述.有一个相同的代码使用mmap
内存分配PROT_EXEC
标志(和工作):
#include#include #include int myfun() { return 42; } int main() { size_t size = (char*)main - (char*)myfun; char *data = mmap(NULL, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); memcpy(data, myfun, size); int (*fun_pointer)() = (void*)data; printf("%d\n", fun_pointer()); munmap(data, size); return 0; }
此示例应符合-fPIC
gcc选项,以确保函数中的代码与位置无关.
那里有几个问题:
您的data
数组保留在数据段中,而不是代码段中.
该地址搬迁没有被处理.
只是猜测,代码大小是未知的.