取消引用 C 中的函数指针以访问 CODE 内存

Dereferencing function pointers in C to access CODE memory

我们这里处理的是C。我只是有这个想法,想知道是否有可能访问内存中存储函数的点,比如 foo 并将函数的内容复制到内存中的另一个点。具体来说,我正在尝试使以下内容起作用:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void foo(){
    printf("Hello World");
}

int main(){

    void (*bar)(void) = malloc(sizeof foo);
    memcpy(&bar, &foo, sizeof foo);


    bar();
    return 0;
}

但是运行它给出了总线错误:Bus error: 10。我正在尝试将函数 foo 的内容复制到内存 bar 的 space 中,然后执行新创建的函数 bar

无非是想看看这样的事情是否可能,揭示C语言的复杂性。我没有考虑它有什么实际用途。

我正在寻找使它起作用的指导,或者以其他方式被告知为什么它不起作用

EDIT 查看一些答案并学习 readwrite可执行 内存,我突然意识到可以通过写入可执行内存在 C 中动态创建函数。

使用标准 C,您尝试做的是实现定义的行为,并且无法移植。在给定的平台上,您也许能够完成这项工作。

记忆malloc 给你的通常是不可执行的。跳到那里会导致总线错误 (SIGBUS)。假设你在一个类似 POSIX 的系统上,或者使用 mmap 为函数分配内存和导致内存区域可执行的标志,或者使用 mprotect 将区域标记为可执行.

您还需要更加小心您提供的内存量,您不能简单地获取函数的大小并期望它是函数的长度,sizeof 并非旨在提供这种功能。您需要使用其他方法找出函数长度。

在现代桌面上,虚拟内存管理器会妨碍您。内存区域有三种访问类型:readwriteexecute。在代码段只有 execute 权限的系统上,memcpy 将因总线错误而失败。在更典型的情况下,只有代码段具有 execute 权限,您可以复制函数,但不能复制 运行,因为包含 bar 的内存区域将没有 执行 权限。

此外,确定函数的大小也存在问题。考虑以下程序

void foo( int *x )
{
    printf( "x:(%zu %zu) ", sizeof x, sizeof *x );
}

int main( void )
{
    int x = 0;
    foo( &x );
    printf( "foo:(%zu %zu)\n", sizeof foo, sizeof *foo );
}

在我的系统上,输出是 x:(8 4) foo:(1 1),表示获取 sizeof 函数指针或函数本身不受支持。