检测C / C ++程序进行的每次内存访问

时间:2016-01-27 14:47:28

标签: c memory trace heap-memory

我试图检测用C / C ++编写的每个访问程序在运行时正在进行,特别是动态分配的内存。另外,我想了解一下访问的位置。进行访问的函数名称就是我要找的。

例如,对于以下代码:

void MemoryAccess(int* my_vector) {
    int x = my_vector[0]; // Read access from 0xFFFF0000.
    my_vector[0] = x + 1; // Write access to 0XFFFF0000.
}

int main(void) {
    // Assume that the address returned by malloc is 0xFFFF0000.
    int* vec = malloc(VEC_SIZE * sizeof(int));
    if (!vec) {
        return MEMORY_ALLOCATION_FAIL;
    }
    MemoryAccess(vec);

    int second_elem = vec[1]; // Read access from 0xFFFF0004.
    v[1] = 10; // Write access to 0xFFFF0004.

    return 0;
}

我想记录一个日志文件,其中包含以下内容:已访问的地址,进行访问的函数名称。对于上面的示例,我的日志应该类似于:

{Read}  {MemoryAccess} {0xFFFF0000}
{Write} {MemoryAccess} {0xFFFF0000}
{Read}  {main}         {0xFFFF0004}
{Write} {main}         {0xFFFF0004}

我已经能够在Windows上使用异常过滤器执行类似的操作,并修改受监视内存块的页面保护。我无法获取进行访问的函数名,只有引发异常时才有指令指针值,而我无法知道如何使用它来获取函数名。

注意:我的目标是在基于Linux的系统(主要是Debian / Ubuntu)上监控内存访问,而不是Windows。

1 个答案:

答案 0 :(得分:2)

(我专注于Linux)

如果天真地完成,你想要做的就是非常慢并且需要不可移植的代码。我想你想要一个通用的解决方案(处理许多C ++程序,而不是某些特定的程序)。

你可以修补一些模拟器,即la Qemu。

也许您只想使用valgrindGCC debugging options地址清理程序(搜索-fsanitize=address)。或使用 gdb观察点。请注意,最近的GDB可以在Python或Guile中编写脚本。

也许你可以从valgrind技巧中获取灵感。

同时查看ptrace(2)

如果您不想要灾难性的表现(即,天真地解释每台机器指令和/或为每次内存访问处理SIGSEGV,请参阅this了解更多信息),您需要处理它。

您可以考虑自定义GCC编译器(例如使用MELT),以便某些(相关的)加载& store在编译器中得到了检测。

如果你采取天真的方法(解释每个机器指令和/或粗略的SIGSEGV处理),你可能会使你的程序减慢超过千分之一,并且“半天真”的方法仍然需要数月工作的。你会遇到Heisenbugs

如果你想要一个认真的方法,你需要修改你的GCC编译器(例如用MELT),这样编译器发出的一些检测代码另外 ,重新编译要检测的程序(以及它正在使用的所有库),这可能至少花费你一年的时间(除非你已经熟悉GCC内部)。

如果您是认真的,请学习更多计算机科学(computer architectureoperating systemscompilers),并让您的博士学位。你需要几年的努力。