Modules using object_ref.
This commit is contained in:
parent
fff1a7c132
commit
5cfb69434c
|
@ -300,7 +300,9 @@ void Debugger::StopSession() {
|
|||
shutdown(listen_socket_, SD_SEND);
|
||||
closesocket(listen_socket_);
|
||||
listen_socket_ = INVALID_SOCKET;
|
||||
if (accept_thread_.joinable()) {
|
||||
accept_thread_.join();
|
||||
}
|
||||
|
||||
functions_file_.reset();
|
||||
functions_trace_file_.reset();
|
||||
|
|
|
@ -38,21 +38,23 @@ Emulator::~Emulator() {
|
|||
// Note that we delete things in the reverse order they were initialized.
|
||||
|
||||
// Kill the debugger first, so that we don't have it messing with things.
|
||||
debugger_.reset();
|
||||
debugger_->StopSession();
|
||||
|
||||
// Give the systems time to shutdown before we delete them.
|
||||
graphics_system_->Shutdown();
|
||||
audio_system_->Shutdown();
|
||||
|
||||
kernel_state_.reset();
|
||||
file_system_.reset();
|
||||
|
||||
input_system_.reset();
|
||||
graphics_system_.reset();
|
||||
audio_system_.reset();
|
||||
|
||||
kernel_state_.reset();
|
||||
file_system_.reset();
|
||||
|
||||
processor_.reset();
|
||||
|
||||
debugger_.reset();
|
||||
|
||||
export_resolver_.reset();
|
||||
|
||||
// Kill the window last, as until the graphics system/etc is dead it's needed.
|
||||
|
@ -198,10 +200,10 @@ X_STATUS Emulator::LaunchSTFSTitle(const std::wstring& path) {
|
|||
|
||||
X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
|
||||
const std::string& module_path) {
|
||||
auto xboxkrnl = static_cast<kernel::XboxkrnlModule*>(
|
||||
kernel_state_->GetModule("xboxkrnl.exe"));
|
||||
auto xboxkrnl_module = kernel_state_->GetModule("xboxkrnl.exe");
|
||||
auto xboxkrnl = kernel::object_ref<kernel::XboxkrnlModule>(
|
||||
reinterpret_cast<kernel::XboxkrnlModule*>(xboxkrnl_module.release()));
|
||||
int result = xboxkrnl->LaunchModule(module_path.c_str());
|
||||
xboxkrnl->Release();
|
||||
if (result == 0) {
|
||||
return X_STATUS_SUCCESS;
|
||||
} else {
|
||||
|
|
|
@ -202,10 +202,11 @@ void CommandProcessor::WorkerThreadMain() {
|
|||
SwitchToThread();
|
||||
MemoryBarrier();
|
||||
write_ptr_index = write_ptr_index_.load();
|
||||
} while (pending_fns_.empty() && (write_ptr_index == 0xBAADF00D ||
|
||||
} while (worker_running_ && pending_fns_.empty() &&
|
||||
(write_ptr_index == 0xBAADF00D ||
|
||||
read_ptr_index_ == write_ptr_index));
|
||||
// ReturnFromWait();
|
||||
if (!pending_fns_.empty()) {
|
||||
if (!worker_running_ || !pending_fns_.empty()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,8 +45,7 @@ KernelState::KernelState(Emulator* emulator)
|
|||
memory_(emulator->memory()),
|
||||
object_table_(nullptr),
|
||||
has_notified_startup_(false),
|
||||
process_type_(X_PROCTYPE_USER),
|
||||
executable_module_(nullptr) {
|
||||
process_type_(X_PROCTYPE_USER) {
|
||||
processor_ = emulator->processor();
|
||||
file_system_ = emulator->file_system();
|
||||
|
||||
|
@ -70,13 +69,8 @@ KernelState::KernelState(Emulator* emulator)
|
|||
KernelState::~KernelState() {
|
||||
SetExecutableModule(nullptr);
|
||||
|
||||
for (auto user_module : user_modules_) {
|
||||
user_module->Release();
|
||||
}
|
||||
executable_module_.reset();
|
||||
user_modules_.clear();
|
||||
for (auto kernel_module : kernel_modules_) {
|
||||
kernel_module->Release();
|
||||
}
|
||||
kernel_modules_.clear();
|
||||
|
||||
// Delete all objects.
|
||||
|
@ -116,7 +110,7 @@ bool KernelState::IsKernelModule(const char* name) {
|
|||
return false;
|
||||
}
|
||||
|
||||
XModule* KernelState::GetModule(const char* name) {
|
||||
object_ref<XModule> KernelState::GetModule(const char* name) {
|
||||
if (!name) {
|
||||
// NULL name = self.
|
||||
// TODO(benvanik): lookup module from caller address.
|
||||
|
@ -128,48 +122,37 @@ XModule* KernelState::GetModule(const char* name) {
|
|||
std::lock_guard<xe::recursive_mutex> lock(object_mutex_);
|
||||
for (auto kernel_module : kernel_modules_) {
|
||||
if (kernel_module->Matches(name)) {
|
||||
kernel_module->Retain();
|
||||
return kernel_module;
|
||||
return retain_object(kernel_module.get());
|
||||
}
|
||||
}
|
||||
for (auto user_module : user_modules_) {
|
||||
if (user_module->Matches(name)) {
|
||||
user_module->Retain();
|
||||
return user_module;
|
||||
return retain_object(user_module.get());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
XUserModule* KernelState::GetExecutableModule() {
|
||||
object_ref<XUserModule> KernelState::GetExecutableModule() {
|
||||
if (!executable_module_) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
executable_module_->Retain();
|
||||
return executable_module_;
|
||||
}
|
||||
|
||||
void KernelState::SetExecutableModule(XUserModule* module) {
|
||||
if (module == executable_module_) {
|
||||
void KernelState::SetExecutableModule(object_ref<XUserModule> module) {
|
||||
if (module.get() == executable_module_.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (executable_module_) {
|
||||
executable_module_->Release();
|
||||
}
|
||||
executable_module_ = module;
|
||||
if (executable_module_) {
|
||||
executable_module_->Retain();
|
||||
}
|
||||
executable_module_ = std::move(module);
|
||||
}
|
||||
|
||||
void KernelState::LoadKernelModule(XKernelModule* kernel_module) {
|
||||
void KernelState::LoadKernelModule(object_ref<XKernelModule> kernel_module) {
|
||||
std::lock_guard<xe::recursive_mutex> lock(object_mutex_);
|
||||
kernel_modules_.push_back(kernel_module);
|
||||
kernel_modules_.push_back(std::move(kernel_module));
|
||||
}
|
||||
|
||||
XUserModule* KernelState::LoadUserModule(const char* raw_name) {
|
||||
object_ref<XUserModule> KernelState::LoadUserModule(const char* raw_name) {
|
||||
// Some games try to load relative to launch module, others specify full path.
|
||||
std::string name = xe::find_name_from_path(raw_name);
|
||||
std::string path(raw_name);
|
||||
|
@ -177,28 +160,28 @@ XUserModule* KernelState::LoadUserModule(const char* raw_name) {
|
|||
path = xe::join_paths(xe::find_base_path(executable_module_->path()), name);
|
||||
}
|
||||
|
||||
XUserModule* module = nullptr;
|
||||
object_ref<XUserModule> module;
|
||||
{
|
||||
std::lock_guard<xe::recursive_mutex> lock(object_mutex_);
|
||||
|
||||
// See if we've already loaded it
|
||||
for (XUserModule* existing_module : user_modules_) {
|
||||
for (auto& existing_module : user_modules_) {
|
||||
if (existing_module->path() == path) {
|
||||
existing_module->Retain();
|
||||
return existing_module;
|
||||
return retain_object(existing_module.get());
|
||||
}
|
||||
}
|
||||
|
||||
// Module wasn't loaded, so load it.
|
||||
module = new XUserModule(this, path.c_str());
|
||||
module = object_ref<XUserModule>(new XUserModule(this, path.c_str()));
|
||||
X_STATUS status = module->LoadFromFile(path);
|
||||
if (XFAILED(status)) {
|
||||
module->Release();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
user_modules_.push_back(module);
|
||||
// Retain when putting into the listing.
|
||||
module->Retain();
|
||||
user_modules_.push_back(module);
|
||||
}
|
||||
|
||||
module->Dump();
|
||||
|
|
|
@ -73,16 +73,16 @@ class KernelState {
|
|||
void RegisterModule(XModule* module);
|
||||
void UnregisterModule(XModule* module);
|
||||
bool IsKernelModule(const char* name);
|
||||
XModule* GetModule(const char* name);
|
||||
XUserModule* GetExecutableModule();
|
||||
void SetExecutableModule(XUserModule* module);
|
||||
object_ref<XModule> GetModule(const char* name);
|
||||
object_ref<XUserModule> GetExecutableModule();
|
||||
void SetExecutableModule(object_ref<XUserModule> module);
|
||||
template <typename T>
|
||||
XKernelModule* LoadKernelModule() {
|
||||
auto kernel_module = std::make_unique<T>(emulator_, this);
|
||||
LoadKernelModule(kernel_module.get());
|
||||
return kernel_module.release();
|
||||
object_ref<XKernelModule> LoadKernelModule() {
|
||||
auto kernel_module = object_ref<XKernelModule>(new T(emulator_, this));
|
||||
LoadKernelModule(kernel_module);
|
||||
return kernel_module;
|
||||
}
|
||||
XUserModule* LoadUserModule(const char* name);
|
||||
object_ref<XUserModule> LoadUserModule(const char* name);
|
||||
|
||||
void RegisterThread(XThread* thread);
|
||||
void UnregisterThread(XThread* thread);
|
||||
|
@ -102,7 +102,7 @@ class KernelState {
|
|||
uint32_t extended_error, uint32_t length);
|
||||
|
||||
private:
|
||||
void LoadKernelModule(XKernelModule* kernel_module);
|
||||
void LoadKernelModule(object_ref<XKernelModule> kernel_module);
|
||||
|
||||
Emulator* emulator_;
|
||||
Memory* memory_;
|
||||
|
@ -122,9 +122,9 @@ class KernelState {
|
|||
bool has_notified_startup_;
|
||||
|
||||
uint32_t process_type_;
|
||||
XUserModule* executable_module_;
|
||||
std::vector<XKernelModule*> kernel_modules_;
|
||||
std::vector<XUserModule*> user_modules_;
|
||||
object_ref<XUserModule> executable_module_;
|
||||
std::vector<object_ref<XKernelModule>> kernel_modules_;
|
||||
std::vector<object_ref<XUserModule>> user_modules_;
|
||||
|
||||
friend class XObject;
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ ObjectTable::~ObjectTable() {
|
|||
table_capacity_ = 0;
|
||||
last_free_entry_ = 0;
|
||||
free(table_);
|
||||
table_ = NULL;
|
||||
table_ = nullptr;
|
||||
}
|
||||
|
||||
X_STATUS ObjectTable::FindFreeSlot(uint32_t* out_slot) {
|
||||
|
|
|
@ -172,7 +172,6 @@ X_STATUS XThread::Create() {
|
|||
tls_address_ = memory()->SystemHeapAlloc(tls_size);
|
||||
if (!tls_address_) {
|
||||
XELOGW("Unable to allocate thread local storage block");
|
||||
module->Release();
|
||||
return X_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -187,10 +186,6 @@ X_STATUS XThread::Create() {
|
|||
memory()->Fill(tls_address_, tls_size, 0);
|
||||
}
|
||||
|
||||
if (module) {
|
||||
module->Release();
|
||||
}
|
||||
|
||||
// Allocate processor thread state.
|
||||
// This is thread safe.
|
||||
thread_state_ = new ThreadState(kernel_state()->processor(), thread_id_,
|
||||
|
|
|
@ -79,8 +79,6 @@ SHIM_CALL XamGetExecutionId_shim(PPCContext* ppc_state, KernelState* state) {
|
|||
|
||||
SHIM_SET_MEM_32(info_ptr, module->execution_info_ptr());
|
||||
|
||||
module->Release();
|
||||
|
||||
SHIM_SET_RETURN_32(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -171,13 +171,12 @@ XboxkrnlModule::~XboxkrnlModule() {
|
|||
int XboxkrnlModule::LaunchModule(const char* path) {
|
||||
// Create and register the module. We keep it local to this function and
|
||||
// dispose it on exit.
|
||||
XUserModule* module = new XUserModule(kernel_state_, path);
|
||||
auto module = object_ref<XUserModule>(new XUserModule(kernel_state_, path));
|
||||
|
||||
// Load the module into memory from the filesystem.
|
||||
X_STATUS result_code = module->LoadFromFile(path);
|
||||
if (XFAILED(result_code)) {
|
||||
XELOGE("Failed to load module %s: %.8X", path, result_code);
|
||||
module->Release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -193,12 +192,9 @@ int XboxkrnlModule::LaunchModule(const char* path) {
|
|||
kernel_state_->SetExecutableModule(NULL);
|
||||
if (XFAILED(result_code)) {
|
||||
XELOGE("Failed to launch module %s: %.8X", path, result_code);
|
||||
module->Release();
|
||||
return 2;
|
||||
}
|
||||
|
||||
module->Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ SHIM_CALL XexCheckExecutablePrivilege_shim(PPCContext* ppc_state,
|
|||
// Privilege=6 -> 0x00000040 -> XEX_SYSTEM_INSECURE_SOCKETS
|
||||
uint32_t mask = 1 << privilege;
|
||||
|
||||
XUserModule* module = state->GetExecutableModule();
|
||||
auto module = state->GetExecutableModule();
|
||||
if (!module) {
|
||||
SHIM_SET_RETURN_32(0);
|
||||
return;
|
||||
|
@ -145,8 +145,6 @@ SHIM_CALL XexCheckExecutablePrivilege_shim(PPCContext* ppc_state,
|
|||
const xe_xex2_header_t* header = xe_xex2_get_header(xex);
|
||||
uint32_t result = (header->system_flags & mask) > 0;
|
||||
|
||||
module->Release();
|
||||
|
||||
SHIM_SET_RETURN_32(result);
|
||||
}
|
||||
|
||||
|
@ -157,7 +155,7 @@ SHIM_CALL XexGetModuleHandle_shim(PPCContext* ppc_state, KernelState* state) {
|
|||
|
||||
XELOGD("XexGetModuleHandle(%s, %.8X)", module_name, module_handle_ptr);
|
||||
|
||||
XModule* module = nullptr;
|
||||
object_ref<XModule> module;
|
||||
if (!module_name) {
|
||||
module = state->GetExecutableModule();
|
||||
} else {
|
||||
|
@ -172,8 +170,6 @@ SHIM_CALL XexGetModuleHandle_shim(PPCContext* ppc_state, KernelState* state) {
|
|||
// NOTE: we don't retain the handle for return.
|
||||
SHIM_SET_MEM_32(module_handle_ptr, module->handle());
|
||||
|
||||
module->Release();
|
||||
|
||||
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -187,10 +183,11 @@ SHIM_CALL XexGetModuleSection_shim(PPCContext* ppc_state, KernelState* state) {
|
|||
XELOGD("XexGetModuleSection(%.8X, %s, %.8X, %.8X)", handle, name, data_ptr,
|
||||
size_ptr);
|
||||
|
||||
XModule* module = NULL;
|
||||
X_STATUS result =
|
||||
X_STATUS result = X_STATUS_INVALID_HANDLE;
|
||||
|
||||
XModule* module = nullptr;
|
||||
state->object_table()->GetObject(handle, (XObject**)&module);
|
||||
if (XSUCCEEDED(result)) {
|
||||
if (module) {
|
||||
uint32_t section_data = 0;
|
||||
uint32_t section_size = 0;
|
||||
result = module->GetSection(name, §ion_data, §ion_size);
|
||||
|
@ -198,7 +195,6 @@ SHIM_CALL XexGetModuleSection_shim(PPCContext* ppc_state, KernelState* state) {
|
|||
SHIM_SET_MEM_32(data_ptr, section_data);
|
||||
SHIM_SET_MEM_32(size_ptr, section_size);
|
||||
}
|
||||
|
||||
module->Release();
|
||||
}
|
||||
|
||||
|
@ -218,16 +214,16 @@ SHIM_CALL XexLoadImage_shim(PPCContext* ppc_state, KernelState* state) {
|
|||
X_STATUS result = X_STATUS_NO_SUCH_FILE;
|
||||
|
||||
X_HANDLE module_handle = X_INVALID_HANDLE_VALUE;
|
||||
XModule* module = state->GetModule(module_name);
|
||||
auto module = state->GetModule(module_name);
|
||||
if (module) {
|
||||
// Existing module found, just add a reference and obtain a handle.
|
||||
result = state->object_table()->AddHandle(module, &module_handle);
|
||||
result = state->object_table()->AddHandle(module.get(), &module_handle);
|
||||
} else {
|
||||
// Not found; attempt to load as a user module.
|
||||
module = state->LoadUserModule(module_name);
|
||||
if (module) {
|
||||
module->RetainHandle();
|
||||
module_handle = module->handle();
|
||||
auto user_module = state->LoadUserModule(module_name);
|
||||
if (user_module) {
|
||||
user_module->RetainHandle();
|
||||
module_handle = user_module->handle();
|
||||
result = X_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +268,7 @@ SHIM_CALL XexGetProcedureAddress_shim(PPCContext* ppc_state,
|
|||
|
||||
XModule* module = NULL;
|
||||
if (!module_handle) {
|
||||
module = state->GetExecutableModule();
|
||||
module = state->GetExecutableModule().get();
|
||||
} else {
|
||||
result =
|
||||
state->object_table()->GetObject(module_handle, (XObject**)&module);
|
||||
|
|
|
@ -397,24 +397,20 @@ SHIM_CALL RtlImageXexHeaderField_shim(PPCContext* ppc_state,
|
|||
// The only ImageField I've seen in the wild is
|
||||
// 0x20401 (XEX_HEADER_DEFAULT_HEAP_SIZE), so that's all we'll support.
|
||||
|
||||
XUserModule* module = NULL;
|
||||
|
||||
// TODO(benvanik): use xex_header_base to dereference this.
|
||||
// Right now we are only concerned with games making this call on their main
|
||||
// module, so this hack is fine.
|
||||
module = state->GetExecutableModule();
|
||||
auto module = state->GetExecutableModule();
|
||||
|
||||
const xe_xex2_header_t* xex_header = module->xex_header();
|
||||
for (size_t n = 0; n < xex_header->header_count; n++) {
|
||||
if (xex_header->headers[n].key == image_field) {
|
||||
uint32_t value = xex_header->headers[n].value;
|
||||
module->Release();
|
||||
SHIM_SET_RETURN_64(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
module->Release();
|
||||
SHIM_SET_RETURN_64(0);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue