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 5efd5e54d..cf050e74e 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 89a2d1289..00d44c818 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 9ece9c69e..286eadaab 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);