From 86e28c6d345122ef2acd4deddb15306ff552747d Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sat, 21 Mar 2026 20:51:36 +0100 Subject: [PATCH] CodeCache: Move bounds check to FEXOfflineCompiler The previous check site would easily fail when loading caches for binaries with multiple executable sections. It makes much more sense to refuse generating caches anyway: The condition effectively checked for invalid code map entries, so FEXOfflineCompiler should reject them as bad inputs. --- FEXCore/Source/Interface/Core/CodeCache.cpp | 11 ----------- Source/Tools/FEXOfflineCompiler/Main.cpp | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/FEXCore/Source/Interface/Core/CodeCache.cpp b/FEXCore/Source/Interface/Core/CodeCache.cpp index efc6ca5cc..bf72b8dce 100644 --- a/FEXCore/Source/Interface/Core/CodeCache.cpp +++ b/FEXCore/Source/Interface/Core/CodeCache.cpp @@ -383,17 +383,6 @@ bool CodeCache::LoadData(Core::InternalThreadState* Thread, std::byte* MappedCac MappedCacheFile += std::span {BlockPtr.second.CodePages}.size_bytes(); } - // Consistency check: VMA regions at the top and end should belong to the same file - auto [min_val, max_val] = ranges::minmax_element(BlockList, std::less {}, &decltype(BlockList)::value_type::first); - auto MinBound = CTX.SyscallHandler->LookupExecutableFileSection(Thread, min_val->first + BinarySection.FileStartVA); - auto MaxBound = CTX.SyscallHandler->LookupExecutableFileSection(Thread, max_val->first + BinarySection.FileStartVA); - if (&MinBound->FileInfo != &BinarySection.FileInfo || &MaxBound->FileInfo != &BinarySection.FileInfo) { - ERROR_AND_DIE_FMT("Cached blocks offsets {:#x}-{:#x} out of bounds for guest library {} ({:016x} @ {:#x}) while trying to load " - "section {:#x}-{:#x}!", - min_val->first, max_val->first, BinarySection.FileInfo.Filename, BinarySection.FileInfo.FileId, - BinarySection.FileStartVA, BinarySection.BeginVA, BinarySection.EndVA); - } - // Constrain BlockList to the given ExecutableFileSectionInfo LOGMAN_THROW_A_FMT(ranges::is_sorted(BlockList, [](auto& a, auto& b) { return a.first < b.first; }), "Expected sorted block list"); auto begin = ranges::lower_bound(BlockList, BinarySection.BeginVA - BinarySection.FileStartVA, std::less {}, &BlockListEntry::first); diff --git a/Source/Tools/FEXOfflineCompiler/Main.cpp b/Source/Tools/FEXOfflineCompiler/Main.cpp index f9290985d..144754f90 100644 --- a/Source/Tools/FEXOfflineCompiler/Main.cpp +++ b/Source/Tools/FEXOfflineCompiler/Main.cpp @@ -201,7 +201,18 @@ static std::optional GenerateSingleCache(FEXCore::ExecutableFileInf { std::vector> LoaderMem; + // Refuse to continue if the block list contains any out-of-bounds blocks. + // This often indicates a corrupted code map. + { + auto [min_val, max_val] = std::ranges::minmax_element(BlockList, std::less {}); + auto MinBound = SyscallHandler->LookupExecutableFileSection(Thread, *min_val + SyscallHandler->VAFileStart); + auto MaxBound = SyscallHandler->LookupExecutableFileSection(Thread, *max_val + SyscallHandler->VAFileStart); + LOGMAN_THROW_A_FMT(MinBound && MaxBound, "Cached blocks offsets {:#x}-{:#x} out of bounds for library {} ({:016x} @ {:#x})!", + *min_val, *max_val, Binary.Filename, Binary.FileId, SyscallHandler->VAFileStart); + } + fmt::print(stderr, "Compiling code...\n"); + FEX_CONFIG_OPT(MaxInst, MAXINST); for (auto Addr : BlockList) { if (!CTX->CheckIfBlockIsCacheable(*Thread, Addr + SyscallHandler->VAFileStart, MaxInst)) {