[Kernel] Added support for loading modules before main
This commit is contained in:
parent
70364e73ae
commit
2969a04145
|
@ -24,6 +24,7 @@
|
|||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/kernel/xmodule.h"
|
||||
|
||||
#include "third_party/crypto/TinySHA1.hpp"
|
||||
|
@ -1062,6 +1063,15 @@ bool XexModule::LoadContinue() {
|
|||
opt_import_libraries->string_table.count);
|
||||
assert_not_null(string_table[library_name_index]);
|
||||
auto library_name = std::string(string_table[library_name_index]);
|
||||
|
||||
if (!kernel_state_->IsModuleLoaded(library_name)) {
|
||||
if (auto module = kernel_state_->LoadUserModule(library_name)) {
|
||||
if (kernel_state_->FinishLoadingUserModule(module, false)) {
|
||||
library_name = module->path();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetupLibraryImports(library_name, library);
|
||||
library_offset += library->size;
|
||||
}
|
||||
|
|
|
@ -217,6 +217,28 @@ bool KernelState::IsKernelModule(const std::string_view name) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool KernelState::IsModuleLoaded(const std::string_view name) {
|
||||
if (name.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto kernel_module : kernel_modules_) {
|
||||
if (kernel_module->Matches(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
|
||||
for (auto user_module : user_modules_) {
|
||||
if (user_module->Matches(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
object_ref<KernelModule> KernelState::GetKernelModule(
|
||||
const std::string_view name) {
|
||||
assert_true(IsKernelModule(name));
|
||||
|
@ -431,9 +453,14 @@ object_ref<UserModule> KernelState::LoadUserModule(
|
|||
auto name = xe::utf8::find_name_from_guest_path(raw_name);
|
||||
std::string path(raw_name);
|
||||
if (name == raw_name) {
|
||||
assert_not_null(executable_module_);
|
||||
path = xe::utf8::join_guest_paths(
|
||||
xe::utf8::find_base_guest_path(executable_module_->path()), name);
|
||||
if (!executable_module_) {
|
||||
path = xe::utf8::join_guest_paths(
|
||||
xe::utf8::find_base_guest_path((*user_modules_.cbegin())->path()),
|
||||
name);
|
||||
} else {
|
||||
path = xe::utf8::join_guest_paths(
|
||||
xe::utf8::find_base_guest_path(executable_module_->path()), name);
|
||||
}
|
||||
}
|
||||
|
||||
object_ref<UserModule> module;
|
||||
|
@ -521,6 +548,9 @@ X_RESULT KernelState::FinishLoadingUserModule(
|
|||
1, // DLL_PROCESS_ATTACH
|
||||
0, // 0 because always dynamic
|
||||
};
|
||||
|
||||
module->is_attached_ = true;
|
||||
|
||||
auto thread_state = XThread::GetCurrentThread()->thread_state();
|
||||
processor()->Execute(thread_state, module->entry_point(), args,
|
||||
xe::countof(args));
|
||||
|
@ -808,9 +838,16 @@ void KernelState::OnThreadExecute(XThread* thread) {
|
|||
if (user_module->is_dll_module() && user_module->entry_point()) {
|
||||
uint64_t args[] = {
|
||||
user_module->handle(),
|
||||
2, // DLL_THREAD_ATTACH
|
||||
0, // 0 because always dynamic
|
||||
user_module->is_attached_
|
||||
? static_cast<uint64_t>(2) // DLL_THREAD_ATTACH - Used to call
|
||||
// DLL for each thread created.
|
||||
: static_cast<uint64_t>(1), // DLL_PROCESS_ATTACH - Used only
|
||||
// once for initialization.
|
||||
0, // 0 because always dynamic
|
||||
};
|
||||
|
||||
user_module->is_attached_ = true;
|
||||
|
||||
processor()->Execute(thread_state, user_module->entry_point(), args,
|
||||
xe::countof(args));
|
||||
}
|
||||
|
|
|
@ -226,6 +226,7 @@ class KernelState {
|
|||
bool RegisterUserModule(object_ref<UserModule> module);
|
||||
void UnregisterUserModule(UserModule* module);
|
||||
bool IsKernelModule(const std::string_view name);
|
||||
bool IsModuleLoaded(const std::string_view name);
|
||||
object_ref<XModule> GetModule(const std::string_view name,
|
||||
bool user_only = false);
|
||||
|
||||
|
|
|
@ -108,6 +108,11 @@ class UserModule : public XModule {
|
|||
ByteStream* stream,
|
||||
const std::string_view path);
|
||||
|
||||
// TODO(Gliniak): This shouldn't be required. It is used for initial DLL
|
||||
// initialization. Which should happen on main thread before main execution
|
||||
// which isn't really possible right now.
|
||||
bool is_attached_ = false;
|
||||
|
||||
private:
|
||||
void CalculateHash();
|
||||
|
||||
|
|
Loading…
Reference in New Issue