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.
This commit is contained in:
Léo Lam 2019-06-30 18:27:00 +02:00
parent 2f7a10eeaa
commit 43d1ee6fb7
3 changed files with 26 additions and 14 deletions

View file

@ -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<u8> 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::Success;
} }
} }
return Loader::ResultStatus::ErrorNotUsed; return Loader::ResultStatus::ErrorNotUsed;
} }
bool NCCHContainer::ApplyIPSPatch(std::vector<u8>& 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<u8> 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, Loader::ResultStatus NCCHContainer::LoadOverrideExeFSSection(const char* name,
std::vector<u8>& buffer) { std::vector<u8>& buffer) {
std::string override_name; std::string override_name;

View file

@ -271,6 +271,13 @@ public:
*/ */
Loader::ResultStatus ReadExtdataId(u64& extdata_id); 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<u8>& code) const;
/** /**
* Checks whether the NCCH container contains an ExeFS * Checks whether the NCCH container contains an ExeFS
* @return bool check result * @return bool check result

View file

@ -100,6 +100,9 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
overlay_ncch->exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE + overlay_ncch->exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE +
bss_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->entrypoint = codeset->CodeSegment().addr;
codeset->memory = std::move(code); codeset->memory = std::move(code);