Chi*_*ggs 9 c linux mmap system-calls signal-handling
我正在编写一个框架来实现在模拟器和未修改的主机软件中运行的RTL的协同仿真.编写主机软件以控制实际硬件,通常以两种方式之一工作:
前一种情况非常简单 - 编写一个库,它实现与驱动程序相同的读/写调用,并在运行模拟时与之相关联.这一切都非常有效,我可以运行未经修改的生产软件作为我的RTL模拟的刺激.
第二种情况比第一种情况要困难得多......
最初我以为我可以LD_PRELOAD
用来拦截mmap调用.在我的实现中,mmap
我会分配一些页面对齐的内存,然后mprotect
设置一个信号处理程序来捕获SIGSEGV
.
这种方法存在许多问题:
读取与写入
我可以确定访问的地址,siginfo_t->si_addr
但不能确定访问是读还是写.
捕获重复访问
在信号处理程序中,我需要取消保护内存区域,否则SIGSEGV
只要我的处理程序退出并且主机代码永远不会继续,我就会重复.但是,如果我取消保护区域,那么我的信号处理程序将不会捕获后续访问.
信号处理程序的肮脏
在模拟器驱动RTL并返回结果时阻塞信号处理程序违反了各种编程规则 - 特别是假设模拟器可以触发各种其他事件并在从此访问返回结果之前执行任意代码.
我想知道是否可以创建一个类似文件的对象,其行为类似于磁盘,而不是mprotect
在缓冲区上使用.我没有找到任何表明这是可行的信息.
是否可以捕获对mmap区域的所有访问以及如何?
假设LD_PRELOAD
并且mprotect
是最佳路线:
mprotect
该区域?在X86上,您可以为调用者的上下文设置Trap标志,以便在一条指令之后获得SIGTRAP(此标志通常用于单步执行).也就是说,遇到SIGSEGV时,在调用者的EFLAGS中设置TF(请参阅参考资料ucontext.h
),启用读取mprotect
并返回.如果使用相同的IP立即重复SIGSEGV,则启用写入(如果要区分读取 - 修改 - 写入和"只写"访问,则可以选择禁用读取).如果从同一IP获取SIGSEGV以进行只读和只写保护,则启用读写.
无论何时获得SIGTRAP,您都可以分析写入的值(如果是写访问权限),还可以重新保护页面以捕获将来的访问.
更正:如果读取和写入都有副作用,请先尝试只写保护,然后应用读取副作用并尝试只读保护,然后在最终的SIGTRAP处理程序中启用写入和处理写入的副作用.
更新:我推荐假设的只写保护,这在大多数架构中都不存在,这是致命的错误.幸运的是,有一种更简单的方法可以知道失败的操作是否尝试读取内存,至少在x86上是这样:
页面错误异常将错误代码推送到堆栈,该堆栈在Linux SIGSEGV处理程序中可用作结构的err
成员sigcontext
.写入错误的错误代码的第1 位为1,否则为0.对于读 - 修改 - 写操作,它最初将为0(在这里你可以模拟读数,确切地知道它会发生).
归档时间: |
|
查看次数: |
2382 次 |
最近记录: |