From 4a3773d2fbab4e4375345358d9b7a5b42fd05d13 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sat, 5 Dec 2015 19:37:48 -0600 Subject: [PATCH] XModule Save/Restore --- src/xenia/kernel/user_module.cc | 32 ++++++++++++++++ src/xenia/kernel/user_module.h | 4 ++ src/xenia/kernel/xmodule.cc | 65 ++++++++++++++++++++++++++------- src/xenia/kernel/xmodule.h | 4 ++ src/xenia/kernel/xobject.cc | 3 +- 5 files changed, 94 insertions(+), 14 deletions(-) diff --git a/src/xenia/kernel/user_module.cc b/src/xenia/kernel/user_module.cc index e6c453f07..287f80edb 100644 --- a/src/xenia/kernel/user_module.cc +++ b/src/xenia/kernel/user_module.cc @@ -304,6 +304,38 @@ object_ref UserModule::Launch(uint32_t flags) { return thread; } +bool UserModule::Save(ByteStream* stream) { + if (!XModule::Save(stream)) { + return false; + } + + // A lot of the information stored on this class can be reconstructed at + // runtime. + + return true; +} + +object_ref UserModule::Restore(KernelState* kernel_state, + ByteStream* stream, + std::string path) { + auto module = new UserModule(kernel_state, path.c_str()); + + // XModule::Save took care of this earlier... + // TODO: Find a nicer way to represent that here. + if (!module->RestoreObject(stream)) { + return false; + } + + auto result = module->LoadFromFile(path); + if (XFAILED(result)) { + XELOGD("UserModule::Restore LoadFromFile(%s) FAILED - code %.8X", + path.c_str(), result); + return false; + } + + return object_ref(module); +} + void UserModule::Dump() { if (module_format_ == kModuleFormatElf) { // Quick die. diff --git a/src/xenia/kernel/user_module.h b/src/xenia/kernel/user_module.h index 16c5e29c5..769abb9b4 100644 --- a/src/xenia/kernel/user_module.h +++ b/src/xenia/kernel/user_module.h @@ -87,6 +87,10 @@ class UserModule : public XModule { void Dump(); + bool Save(ByteStream* stream) override; + static object_ref Restore(KernelState* kernel_state, + ByteStream* stream, std::string path); + private: uint32_t guest_xex_header_ = 0; ModuleFormat module_format_ = kModuleFormatUndefined; diff --git a/src/xenia/kernel/xmodule.cc b/src/xenia/kernel/xmodule.cc index 7fdbd7f8e..5a23ce945 100644 --- a/src/xenia/kernel/xmodule.cc +++ b/src/xenia/kernel/xmodule.cc @@ -9,8 +9,10 @@ #include "xenia/kernel/xmodule.h" +#include "xenia/base/byte_stream.h" #include "xenia/base/string.h" #include "xenia/kernel/kernel_state.h" +#include "xenia/kernel/user_module.h" namespace xe { namespace kernel { @@ -22,19 +24,7 @@ XModule::XModule(KernelState* kernel_state, ModuleType module_type, path_(path), processor_module_(nullptr), hmodule_ptr_(0) { - auto last_slash = path.find_last_of('/'); - if (last_slash == path.npos) { - last_slash = path.find_last_of('\\'); - } - if (last_slash == path.npos) { - name_ = path_; - } else { - name_ = path_.substr(last_slash + 1); - } - auto dot = name_.find_last_of('.'); - if (dot != name_.npos) { - name_ = name_.substr(0, dot); - } + name_ = NameFromPath(path); // Loader data (HMODULE) hmodule_ptr_ = memory()->SystemHeapAlloc(sizeof(X_LDR_DATA_TABLE_ENTRY)); @@ -86,5 +76,54 @@ uint32_t XModule::GetHandleFromHModule(void* hmodule) { return ldr_data->checksum; } +std::string XModule::NameFromPath(std::string path) { + std::string name; + auto last_slash = path.find_last_of('/'); + if (last_slash == path.npos) { + last_slash = path.find_last_of('\\'); + } + if (last_slash == path.npos) { + name = path; + } else { + name = path.substr(last_slash + 1); + } + auto dot = name.find_last_of('.'); + if (dot != name.npos) { + name = name.substr(0, dot); + } + + return name; +} + +bool XModule::Save(ByteStream* stream) { + stream->Write('XMOD'); + + stream->Write(path_); + stream->Write(hmodule_ptr_); + + if (!SaveObject(stream)) { + return false; + } + + return true; +} + +object_ref XModule::Restore(KernelState* kernel_state, + ByteStream* stream) { + if (stream->Read() != 'XMOD') { + return false; + } + + auto path = stream->Read(); + auto hmodule_ptr = stream->Read(); + + // Can only save user modules at the moment, so just redirect. + // TODO: Find a way to call RestoreObject here before UserModule::Restore. + auto module = UserModule::Restore(kernel_state, stream, path); + + module->hmodule_ptr_ = hmodule_ptr; + return module; +} + } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xmodule.h b/src/xenia/kernel/xmodule.h index b772f443c..22b7b053a 100644 --- a/src/xenia/kernel/xmodule.h +++ b/src/xenia/kernel/xmodule.h @@ -80,9 +80,13 @@ class XModule : public XObject { void* hmodule); static uint32_t GetHandleFromHModule(void* hmodule); + virtual bool Save(ByteStream* stream) override; + static object_ref Restore(KernelState* kernel_state, ByteStream* stream); + protected: void OnLoad(); void OnUnload(); + static std::string NameFromPath(std::string path); ModuleType module_type_; std::string name_; diff --git a/src/xenia/kernel/xobject.cc b/src/xenia/kernel/xobject.cc index 83b66ec68..9a1cb4415 100644 --- a/src/xenia/kernel/xobject.cc +++ b/src/xenia/kernel/xobject.cc @@ -19,6 +19,7 @@ #include "xenia/kernel/xenumerator.h" #include "xenia/kernel/xevent.h" #include "xenia/kernel/xfile.h" +#include "xenia/kernel/xmodule.h" #include "xenia/kernel/xmutant.h" #include "xenia/kernel/xsemaphore.h" #include "xenia/kernel/xthread.h" @@ -129,7 +130,7 @@ object_ref XObject::Restore(KernelState* kernel_state, Type type, case kTypeIOCompletion: break; case kTypeModule: - break; + return XModule::Restore(kernel_state, stream); case kTypeMutant: break; case kTypeNotifyListener: