繁体   English   中英

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

[英]WinAPI: Is it needed to call FlushInstructionCache on an executable memory-mapped file?

我写了一个简短的程序来读取一个windows obj文件并找到.text部分并在其中运行代码。 为此,我进行了以下Windows API函数调用( 完整代码[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页面上没有这样的注释。

如果你只使用MapViewOfFile将文件内容加载到内存中,那么它应该没问题。

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

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

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

  2. 因为很难预测缓存中可能存在的内容 - 处理器具有各种“聪明”的预取方式,并且通常可以“填充”缓存。

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

修改包括“修复绝对地址”(例如,如果要完成加载复杂的项目以执行它,则必须执行的操作),或者如果编写调试器,则在通过替换设置断点时在x86上使用INT 3指令的指令。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM