WinAPI:是否需要在可执行的内存映射文件上调用FlushInstructionCache?

时间:2017-02-27 06:36:02

标签: c++ windows winapi memory-mapped-files self-modifying

我编写了一个简短的程序来读取windows obj文件并找到.text部分并在其中运行代码。为此,我为感兴趣的人做了以下Windows API函数调用(Full code [gist.github.com]):

HANDLE FileHandle = CreateFile("lib.obj",
                               GENERIC_READ | GENERIC_EXECUTE,
                               FILE_SHARE_READ, 0,
                               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

HANDLE MappingHandle = CreateFileMapping(FileHandle, 0, PAGE_EXECUTE_READ, 0, 0, 0);

void *Address = MapViewOfFile(MappingHandle, FILE_MAP_EXECUTE | FILE_MAP_READ,
                              0, 0, 0);

然后我在文件中找到.text部分,并将指针转换为C ++中的函数指针代码,然后简单地调用该函数。这实际上似乎对我有用。

我是否在映射到文件的虚拟内存范围内调用FlushInstructonCache时出错?

我问这个是因为我最近阅读了VirtualAlloc文档,并在底部注明:

  

当创建一个可执行的区域时,一旦代码设置到位,调用程序就会负责通过适当调用FlushInstructionCache来确保缓存一致性。否则,尝试从新的可执行区域执行代码可能会产生不可预测的结果。

我的代码是否可能导致CPU在指令缓存中执行旧指令?

MapViewOfFileCreateFileMapping页面上没有此类注释。

1 个答案:

答案 0 :(得分:7)

如果您只使用MapViewOfFile将文件内容加载到内存中,则应该没有。

如果修改内存中的内容,则需要在执行代码之前刷新instructioncache,因为它可能以未修改的形式存在于缓存中,然后可以在不进行修改的情况下执行。

我使用MAY这个词是因为两件事:

  1. 这取决于处理器架构,处理器是否检测到要执行的内存的写入[某些处理器甚至没有硬件来注册写入指令缓存中的数据 - 因为它&# 39;非常罕见,以至于不太可能]。

  2. 因为很难预测缓存中的内容 - 处理器 各种各样的"聪明"预取的方法和一般的#34;填充" 高速缓存。

  3. 显然,VirtualAlloc没有机会包含您想要的数据,因此在那里提到它是因为您在执行之前始终会写入数据。

    修改包括"修复绝对地址"例如(如果你想完成一个加载一些复杂的项目来执行它,你必须做的事情),或者如果你编写一个调试器,当你通过用{{1}替换一个指令来设置一个断点时关于x86的指令。

    第二个案例"修改"如果你卸载文件,并加载一个不同的文件(例如"相同的"文件,但重建,例如),在这种情况下,以前执行的代码可能仍然在缓存中,你得到神秘的"为什么我的改变不符合我的期望"