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:
parent
2f7a10eeaa
commit
43d1ee6fb7
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user