【问题标题】:Custom handling of memory reads and writes in C在 C 中自定义处理内存读取和写入
【发布时间】:2020-04-18 07:23:41
【问题描述】:

我正在编写自己的 malloc 并使用 LD_PRELOAD 技巧来使用它。我需要能够为对堆的每次内存访问执行自定义功能,包括读取和写入(性能不是问题,功能是目标)。

例如,对于一些类似的代码

int x = A[5];

我希望能够捕获来自(A + 5) 的读取,而不是从该内存位置读取,而是返回我自己的自定义值以存储在x 中。

我目前的想法是:

  1. mprotect 离开,处理生成的 SIGSEGV 并在处理程序中做我需要做的事情。据我所知,我可以访问void *si_addr 中的错误地址,但我不确定如何区分读取和写入 - 即使我确实做到了,我也不知道如何处理写入,因为我不知道要在处理程序中写入的值。
  2. 调整 gcc 以专门处理内存访问。根据我的阅读,理解 gcc 代码需要一段时间,除非它的 IR/抽象程序集方便地隔离内存加载/存储,否则我不确定这有多实用。

欢迎提出任何建议。

【问题讨论】:

  • 如果没有内核支持和对编译器代码生成器的普遍修改,我看不出它是如何在本机工作的。我估计这项任务非常艰巨。实现支持所需语义的虚拟机可能更容易,但如果您必须从头开始,这仍然是一项艰巨的工作。
  • 如果不限于LD_PRELOADing,还可以动态重写将要执行的代码,就像valgrind的memcheck和Sun的dbx的memory access checking一样。

标签: c gcc memory malloc


【解决方案1】:

最简单的方法是通过 malloc(您可能想要拥有 mmap、munmap、mprotect、sig(action, nal, etc) ... 以获得全面覆盖)。您的返回地址与有效映射不对应,捕获 SIGBUS + SIGSEGV,解释 siginfo 结构以修复您的进程,......但这在某种程度上仅限于在堆上操作,并且程序可以很容易地从中逃脱,如果您正试图捕获一个行为不端的程序,该程序可能会破坏您的查找表。

要获得更全面的覆盖,您可能需要查看 gvisor,它被称为容器运行时沙箱。它的技术更接近于调试器,因为它可以完全控制目标,捕获其故障、系统调用等,并管理其地址空间。可能需要进行小手术来适应您的需求。

在任何一种情况下,当您出现故障时,您都必须安装内存并重新启动程序或模拟指令。如果您正在处理像 riscv 或 ARM 这样的干净架构,仿真还不错,但是对于像 x86 这样的过度放纵的架构,您几乎需要集成 qemu。如果采取类似gvisor的方式,可以安装页面并设置单步标志,然后在单步陷阱上移除页面,这样就省事了一些。 dtrace 有一个前身,称为 atrace,它使用这种方法来分析缓存和 tlb 访问模式。

听起来是个有趣的项目;希望一切顺利。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 2012-04-13
    • 2016-08-17
    • 2020-03-04
    相关资源
    最近更新 更多