mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 09:00:17 +02:00
Merge pull request #5655 from neobrain/feature_woa_cache_loading
Windows/ImageTracker: Adapt code cache loading logic to FEXOfflineCompiler
This commit is contained in:
1 file changed
+30
-69
@@ -167,6 +167,8 @@ FEXCore::ExecutableFileSectionInfo ImageTracker::HandleImageMap(std::string_view
|
||||
Writer->AppendSetMainExecutable(ImageInfo->Info);
|
||||
CTX.SetCodeMapWriter(std::move(Writer));
|
||||
}
|
||||
}
|
||||
if (!ActiveCodeMapPath.empty()) {
|
||||
LoadAOTImages(*ImageInfo);
|
||||
}
|
||||
|
||||
@@ -220,84 +222,43 @@ int ImageTracker::OpenCodeMapFile() {
|
||||
}
|
||||
|
||||
void ImageTracker::LoadAOTImages(MappedImageInfo& ImageInfo) {
|
||||
const auto AnsiPath =
|
||||
fmt::format("\\??\\{}cache\\{}", FEX::Config::GetCacheDirectory(), FEXCore::CodeMap::GetBaseFilename(ImageInfo.Info, false));
|
||||
|
||||
// Iterate over all files in the given executable's cache directory, mapping them into memory for future use.
|
||||
// Each cache file name matches the unique ID (as returned by FEXCore::CodeMap::GetBaseFilename) of the image it corresponds to.
|
||||
ScopedUnicodeString NtPath(AnsiPath.c_str());
|
||||
|
||||
OBJECT_ATTRIBUTES DirAttr;
|
||||
InitializeObjectAttributes(&DirAttr, &*NtPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
|
||||
ScopedHandle DirHandle;
|
||||
IO_STATUS_BLOCK IOSB;
|
||||
if (!NT_SUCCESS(NtOpenFile(&*DirHandle, FILE_LIST_DIRECTORY | SYNCHRONIZE, &DirAttr, &IOSB, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT))) {
|
||||
// Don't attempt cache loading for FEXOfflineCompiler itself
|
||||
static bool IsFOC = ImageInfo.Info.Filename.ends_with("fexofflinecompiler.exe");
|
||||
if (IsFOC) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<uint8_t, 0x1000> DirBuffer;
|
||||
bool FirstScan = true;
|
||||
auto QueryDir = [&]() {
|
||||
NTSTATUS Status = NtQueryDirectoryFile(*DirHandle, nullptr, nullptr, nullptr, &IOSB, DirBuffer.data(), DirBuffer.size(),
|
||||
FileBothDirectoryInformation, FALSE, nullptr, FirstScan);
|
||||
if (FirstScan) {
|
||||
FirstScan = false;
|
||||
}
|
||||
return NT_SUCCESS(Status);
|
||||
};
|
||||
auto ID = FEXCore::CodeMap::GetBaseFilename(ImageInfo.Info, false);
|
||||
const uint64_t CodeCacheConfigId = 0; // TODO
|
||||
const auto AnsiPath = fmt::format("\\??\\{}cache\\{}-{:016x}", FEX::Config::GetCacheDirectory(), ID, CodeCacheConfigId);
|
||||
|
||||
while (QueryDir()) {
|
||||
auto* Info = reinterpret_cast<PFILE_BOTH_DIRECTORY_INFORMATION>(DirBuffer.data());
|
||||
IO_STATUS_BLOCK IOSB;
|
||||
ScopedUnicodeString CurrentFileName(AnsiPath.c_str());
|
||||
|
||||
while (true) {
|
||||
UNICODE_STRING CurrentFileName;
|
||||
CurrentFileName.Buffer = Info->FileName;
|
||||
CurrentFileName.Length = static_cast<USHORT>(Info->FileNameLength);
|
||||
CurrentFileName.MaximumLength = CurrentFileName.Length;
|
||||
OBJECT_ATTRIBUTES FileAttr;
|
||||
InitializeObjectAttributes(&FileAttr, &*CurrentFileName, OBJ_CASE_INSENSITIVE, nullptr, nullptr);
|
||||
|
||||
bool Skip = (Info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) || (Info->FileNameLength == 2 && Info->FileName[0] == '.') ||
|
||||
(Info->FileNameLength == 4 && Info->FileName[0] == '.' && Info->FileName[1] == '.');
|
||||
ScopedHandle FileHandle;
|
||||
if (NT_SUCCESS(NtOpenFile(&*FileHandle, GENERIC_READ | SYNCHRONIZE, &FileAttr, &IOSB, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT))) {
|
||||
ScopedHandle SectionHandle;
|
||||
if (NT_SUCCESS(NtCreateSection(&*SectionHandle, SECTION_MAP_EXECUTE | SECTION_MAP_READ, nullptr, nullptr, PAGE_EXECUTE_READ, SEC_COMMIT,
|
||||
*FileHandle))) {
|
||||
void* LoadAddress = nullptr;
|
||||
SIZE_T MappedSize = 0;
|
||||
if (NT_SUCCESS(NtMapViewOfSection(*SectionHandle, NtCurrentProcess(), &LoadAddress, 0, 0, nullptr, &MappedSize, ViewUnmap,
|
||||
MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READ))) {
|
||||
|
||||
if (!Skip) {
|
||||
OBJECT_ATTRIBUTES FileAttr;
|
||||
InitializeObjectAttributes(&FileAttr, &CurrentFileName, OBJ_CASE_INSENSITIVE, *DirHandle, nullptr);
|
||||
|
||||
ScopedHandle FileHandle;
|
||||
if (NT_SUCCESS(NtOpenFile(&*FileHandle, GENERIC_READ | SYNCHRONIZE, &FileAttr, &IOSB, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT))) {
|
||||
ScopedHandle SectionHandle;
|
||||
if (NT_SUCCESS(NtCreateSection(&*SectionHandle, SECTION_MAP_EXECUTE | SECTION_MAP_READ, nullptr, nullptr, PAGE_EXECUTE_READ,
|
||||
SEC_COMMIT, *FileHandle))) {
|
||||
void* LoadAddress = nullptr;
|
||||
SIZE_T MappedSize = 0;
|
||||
if (NT_SUCCESS(NtMapViewOfSection(*SectionHandle, NtCurrentProcess(), &LoadAddress, 0, 0, nullptr, &MappedSize, ViewUnmap,
|
||||
MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READ))) {
|
||||
fextl::string UniqueId;
|
||||
ULONG AnsiLength = 0;
|
||||
RtlUnicodeToMultiByteSize(&AnsiLength, Info->FileName, Info->FileNameLength);
|
||||
UniqueId.resize(AnsiLength);
|
||||
RtlUnicodeToMultiByteN(UniqueId.data(), AnsiLength, NULL, Info->FileName, Info->FileNameLength);
|
||||
|
||||
auto CacheSpan = std::span {static_cast<std::byte*>(LoadAddress), MappedSize};
|
||||
auto MappedCache = CTX.GetCodeCache().LoadCache(CacheSpan, ImageInfo.Info, ImageInfo.SectionInfo.FileStartVA);
|
||||
if (MappedCache) {
|
||||
CTX.GetCodeCache().RegisterMappedCodeBuffer(*MappedCache);
|
||||
AOTImages[UniqueId] = {.CacheFile = std::move(MappedCache)};
|
||||
LogMan::Msg::IFmt("Loaded cache: {}", UniqueId);
|
||||
} else {
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), LoadAddress);
|
||||
LogMan::Msg::EFmt("Failed to load cache: {}", UniqueId);
|
||||
}
|
||||
}
|
||||
}
|
||||
auto CacheSpan = std::span {static_cast<std::byte*>(LoadAddress), MappedSize};
|
||||
auto MappedCache = CTX.GetCodeCache().LoadCache(CacheSpan, ImageInfo.Info, ImageInfo.SectionInfo.FileStartVA);
|
||||
if (MappedCache) {
|
||||
CTX.GetCodeCache().RegisterMappedCodeBuffer(*MappedCache);
|
||||
AOTImages[ID] = {.CacheFile = std::move(MappedCache)};
|
||||
LogMan::Msg::IFmt("Loaded cache: {}", ID);
|
||||
} else {
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), LoadAddress);
|
||||
LogMan::Msg::EFmt("Failed to load cache: {}", ID);
|
||||
}
|
||||
}
|
||||
|
||||
if (Info->NextEntryOffset == 0) {
|
||||
break;
|
||||
}
|
||||
Info = reinterpret_cast<PFILE_BOTH_DIRECTORY_INFORMATION>(reinterpret_cast<uint8_t*>(Info) + Info->NextEntryOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user