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

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

本文关键字:映射 文件 FlushInstructionCache 调用 内存 可执行 是否 Winapi      更新时间:2023-10-16

我编写了一个简短的程序来读取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);
然后,

i然后在文件中找到.TEXT部分,并将指针指向C 中的函数指针,然后简单地调用该函数。这实际上对我有用。

我是否犯了一个错误

我之所

创建可以执行的区域时,调用程序负责通过适当的调用将代码设置在适当的位置,以确保通过适当的拨打拨挡填充缓存相干性。否则,试图从新可执行的区域中执行代码可能会产生不可预测的结果。

我的代码可能会导致CPU在指令缓存中执行旧说明?

MapViewOffile或CreateFileMapping页面上没有这样的注释。

如果仅使用 MapViewOfFile加载文件容器,则应该没关系。

如果您在内存中修改内容,则需要在执行代码之前刷新指令cache,因为它可能以未修饰的形式存在缓存中,然后可以在没有修改的情况下执行。

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

  1. 取决于处理器体系结构是否检测到即将执行的记忆的写入[某些处理器甚至没有硬件要注册的硬件写入指令caches中的数据 - 因为很少见这不太可能]。

  2. ,因为很难预测缓存中的内容 - 处理器拥有各种"聪明"的方式来预取和"填充"缓存。

显然,VirtualAlloc的机会零包含您想要的数据,因此在此提到,因为您始终在执行之前写信。

修改包括"修复绝对地址"(例如,如果您想完成一个要加载一些复杂的项目以执行它的项目,或者在设置Breakpoint时,您必须要做的事情)或通过用x86上的INT 3指令替换指令。

"修改"的第二种情况是,如果您卸载文件,并加载其他文件(例如,"相同"文件,但重建),在这种情况下,先前执行的代码仍然可能位于缓存,您会得到神秘的"为什么我的更改不做我期望的事情"