Initial support for xex patching
This commit is contained in:
@@ -406,6 +406,9 @@ object_ref<UserModule> KernelState::LoadUserModule(
|
||||
}
|
||||
|
||||
module->Dump();
|
||||
emulator_->patcher()->ApplyPatchesForTitle(memory_, module->title_id(),
|
||||
module->hash());
|
||||
emulator_->on_patch_apply();
|
||||
|
||||
if (module->is_dll_module() && module->entry_point() && call_entry) {
|
||||
// Call DllMain(DLL_PROCESS_ATTACH):
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "xenia/base/byte_stream.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/xxhash.h"
|
||||
#include "xenia/cpu/elf_module.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/cpu/xex_module.h"
|
||||
@@ -128,6 +129,9 @@ X_STATUS UserModule::LoadFromFile(const std::string_view path) {
|
||||
}
|
||||
}
|
||||
|
||||
CalculateHash();
|
||||
|
||||
XELOGI("Module hash: {:016X} for {}", hash_.value_or(UINT64_MAX), name_);
|
||||
return LoadXexContinue();
|
||||
}
|
||||
|
||||
@@ -804,5 +808,46 @@ void UserModule::Dump() {
|
||||
xe::logging::AppendLogLine(xe::LogLevel::Info, 'i', sb.to_string_view());
|
||||
}
|
||||
|
||||
void UserModule::CalculateHash() {
|
||||
const BaseHeap* module_heap =
|
||||
kernel_state_->memory()->LookupHeap(xex_module()->base_address());
|
||||
|
||||
if (!module_heap) {
|
||||
XELOGE("Invalid heap for xex module! Address: {:08X}",
|
||||
xex_module()->base_address());
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t page_size = module_heap->page_size();
|
||||
auto security_info = xex_module()->xex_security_info();
|
||||
|
||||
auto find_code_section_page = [&security_info](bool from_bottom) {
|
||||
for (uint32_t i = 0; i < security_info->page_descriptor_count; i++) {
|
||||
const uint32_t page_index =
|
||||
from_bottom ? i : security_info->page_descriptor_count - i;
|
||||
xex2_page_descriptor page_descriptor;
|
||||
page_descriptor.value =
|
||||
xe::byte_swap(security_info->page_descriptors[page_index].value);
|
||||
if (page_descriptor.info != XEX_SECTION_CODE) {
|
||||
continue;
|
||||
}
|
||||
return page_index;
|
||||
}
|
||||
return UINT32_MAX;
|
||||
};
|
||||
|
||||
const uint32_t start_address =
|
||||
xex_module()->base_address() + (find_code_section_page(true) * page_size);
|
||||
const uint32_t end_address =
|
||||
xex_module()->base_address() +
|
||||
((find_code_section_page(false) + 1) * page_size);
|
||||
|
||||
uint8_t* base_code_adr = memory()->TranslateVirtual(start_address);
|
||||
|
||||
XXH3_state_t hash_state;
|
||||
XXH3_64bits_reset(&hash_state);
|
||||
XXH3_64bits_update(&hash_state, base_code_adr, end_address - start_address);
|
||||
hash_ = XXH3_64bits_digest(&hash_state);
|
||||
}
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -38,6 +38,7 @@ class UserModule : public XModule {
|
||||
|
||||
const std::string& path() const override { return path_; }
|
||||
const std::string& name() const override { return name_; }
|
||||
std::optional<uint64_t> hash() const { return hash_; }
|
||||
|
||||
enum ModuleFormat {
|
||||
kModuleFormatUndefined = 0,
|
||||
@@ -97,9 +98,11 @@ class UserModule : public XModule {
|
||||
|
||||
private:
|
||||
X_STATUS LoadXexContinue();
|
||||
void CalculateHash();
|
||||
|
||||
std::string name_;
|
||||
std::string path_;
|
||||
std::optional<uint64_t> hash_ = std::nullopt;
|
||||
|
||||
uint32_t guest_xex_header_ = 0;
|
||||
ModuleFormat module_format_ = kModuleFormatUndefined;
|
||||
|
||||
Reference in New Issue
Block a user