From 43d1ee6fb7c3297f9d0b147b41fbb92fc1a38541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 30 Jun 2019 18:27:00 +0200 Subject: [PATCH] ncch_container: Apply IPS patch after allocating .bss This allows an IPS patch to edit .bss. This is useful for game patches that need to add code, as putting things in .bss allows adding new code *without* editing .code and thus without having to relocate everything. --- src/core/file_sys/ncch_container.cpp | 30 +++++++++++++++------------- src/core/file_sys/ncch_container.h | 7 +++++++ src/core/loader/ncch.cpp | 3 +++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/core/file_sys/ncch_container.cpp b/src/core/file_sys/ncch_container.cpp index 5efd5e54de..cf050e74e3 100644 --- a/src/core/file_sys/ncch_container.cpp +++ b/src/core/file_sys/ncch_container.cpp @@ -539,26 +539,28 @@ Loader::ResultStatus NCCHContainer::LoadSectionExeFS(const char* name, std::vect } } - std::string override_ips = filepath + ".exefsdir/code.ips"; - - if (FileUtil::Exists(override_ips) && strcmp(name, ".code") == 0) { - FileUtil::IOFile ips_file(override_ips, "rb"); - std::size_t ips_file_size = ips_file.GetSize(); - std::vector ips(ips_file_size); - - if (ips_file.IsOpen() && - ips_file.ReadBytes(&ips[0], ips_file_size) == ips_file_size) { - LOG_INFO(Service_FS, "File {} patching code.bin", override_ips); - ApplyIPS(ips, buffer); - } - } - return Loader::ResultStatus::Success; } } return Loader::ResultStatus::ErrorNotUsed; } +bool NCCHContainer::ApplyIPSPatch(std::vector& code) const { + const std::string override_ips = filepath + ".exefsdir/code.ips"; + + FileUtil::IOFile ips_file{override_ips, "rb"}; + if (!ips_file) + return false; + + std::vector ips(ips_file.GetSize()); + if (ips_file.ReadBytes(ips.data(), ips.size()) != ips.size()) + return false; + + LOG_INFO(Service_FS, "File {} patching code.bin", override_ips); + ApplyIPS(ips, code); + return true; +} + Loader::ResultStatus NCCHContainer::LoadOverrideExeFSSection(const char* name, std::vector& buffer) { std::string override_name; diff --git a/src/core/file_sys/ncch_container.h b/src/core/file_sys/ncch_container.h index 89a2d12898..00d44c8180 100644 --- a/src/core/file_sys/ncch_container.h +++ b/src/core/file_sys/ncch_container.h @@ -271,6 +271,13 @@ public: */ Loader::ResultStatus ReadExtdataId(u64& extdata_id); + /** + * Apply an IPS patch for .code (if it exists). + * This should only be called after allocating .bss. + * @return bool true if a patch was applied, false otherwise + */ + bool ApplyIPSPatch(std::vector& code) const; + /** * Checks whether the NCCH container contains an ExeFS * @return bool check result diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 9ece9c69e9..286eadaab2 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -100,6 +100,9 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr& process) overlay_ncch->exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE + bss_page_size; + // Apply any IPS patch now that the entire codeset (including .bss) has been allocated + overlay_ncch->ApplyIPSPatch(code); + codeset->entrypoint = codeset->CodeSegment().addr; codeset->memory = std::move(code);