Merge pull request #213 from DrChat/user_module_imports
User module imports
This commit is contained in:
commit
0dac9f3f02
|
@ -18,21 +18,25 @@
|
||||||
#include "xenia/cpu/cpu-private.h"
|
#include "xenia/cpu/cpu-private.h"
|
||||||
#include "xenia/cpu/export_resolver.h"
|
#include "xenia/cpu/export_resolver.h"
|
||||||
#include "xenia/cpu/processor.h"
|
#include "xenia/cpu/processor.h"
|
||||||
|
#include "xenia/kernel/kernel_state.h"
|
||||||
|
#include "xenia/kernel/objects/xmodule.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
|
|
||||||
using namespace xe::cpu;
|
using namespace xe::cpu;
|
||||||
|
using namespace xe::kernel;
|
||||||
|
|
||||||
using PPCContext = xe::cpu::frontend::PPCContext;
|
using PPCContext = xe::cpu::frontend::PPCContext;
|
||||||
|
|
||||||
void UndefinedImport(PPCContext* ppc_state, void* arg0, void* arg1) {
|
void UndefinedImport(PPCContext* ppc_state, void* arg0, void* arg1) {
|
||||||
XELOGE("call to undefined kernel import");
|
XELOGE("call to undefined import");
|
||||||
}
|
}
|
||||||
|
|
||||||
XexModule::XexModule(Processor* processor)
|
XexModule::XexModule(Processor* processor, KernelState* state)
|
||||||
: Module(processor),
|
: Module(processor),
|
||||||
processor_(processor),
|
processor_(processor),
|
||||||
|
kernel_state_(state),
|
||||||
xex_(nullptr),
|
xex_(nullptr),
|
||||||
base_address_(0),
|
base_address_(0),
|
||||||
low_address_(0),
|
low_address_(0),
|
||||||
|
@ -104,8 +108,23 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||||
for (size_t n = 0; n < import_info_count; n++) {
|
for (size_t n = 0; n < import_info_count; n++) {
|
||||||
const xe_xex2_import_info_t* info = &import_infos[n];
|
const xe_xex2_import_info_t* info = &import_infos[n];
|
||||||
|
|
||||||
KernelExport* kernel_export =
|
// Strip off the extension (for the symbol name)
|
||||||
|
std::string libname = library->name;
|
||||||
|
auto dot = libname.find_last_of('.');
|
||||||
|
if (dot != libname.npos) {
|
||||||
|
libname = libname.substr(0, dot);
|
||||||
|
}
|
||||||
|
|
||||||
|
KernelExport* kernel_export = NULL; // kernel export info
|
||||||
|
uint32_t user_export_addr = 0; // user export address
|
||||||
|
|
||||||
|
if (kernel_state_->IsKernelModule(library->name)) {
|
||||||
|
kernel_export =
|
||||||
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
||||||
|
} else {
|
||||||
|
XModule* module = kernel_state_->GetModule(library->name);
|
||||||
|
user_export_addr = module->GetProcAddressByOrdinal(info->ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
if (kernel_export) {
|
if (kernel_export) {
|
||||||
if (info->thunk_address) {
|
if (info->thunk_address) {
|
||||||
|
@ -114,7 +133,7 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||||
snprintf(name, xe::countof(name), "%s", kernel_export->name);
|
snprintf(name, xe::countof(name), "%s", kernel_export->name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(name, xe::countof(name), "__imp_%s_%.3X", library->name,
|
snprintf(name, xe::countof(name), "__imp_%s_%.3X", libname,
|
||||||
info->ordinal);
|
info->ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,16 +170,26 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||||
kernel_export->name);
|
kernel_export->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
auto slot = memory_->TranslateVirtual<uint32_t*>(info->value_address);
|
||||||
|
|
||||||
|
// Assuming this is correct...
|
||||||
|
xe::store_and_swap<uint32_t>(slot, user_export_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->thunk_address) {
|
if (info->thunk_address) {
|
||||||
if (kernel_export) {
|
if (kernel_export) {
|
||||||
snprintf(name, xe::countof(name), "%s", kernel_export->name);
|
snprintf(name, xe::countof(name), "%s", kernel_export->name);
|
||||||
|
} else if (user_export_addr) {
|
||||||
|
snprintf(name, xe::countof(name), "__%s_%.3X", libname,
|
||||||
|
info->ordinal);
|
||||||
} else {
|
} else {
|
||||||
snprintf(name, xe::countof(name), "__kernel_%s_%.3X", library->name,
|
snprintf(name, xe::countof(name), "__kernel_%s_%.3X", libname,
|
||||||
info->ordinal);
|
info->ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kernel exports go up to the host shim functions
|
||||||
|
if (kernel_export) {
|
||||||
// On load we have something like this in memory:
|
// On load we have something like this in memory:
|
||||||
// li r3, 0
|
// li r3, 0
|
||||||
// li r4, 0x1F5
|
// li r4, 0x1F5
|
||||||
|
@ -198,6 +227,20 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
||||||
fn_info->set_name(name);
|
fn_info->set_name(name);
|
||||||
fn_info->SetupExtern(handler, handler_data, NULL);
|
fn_info->SetupExtern(handler, handler_data, NULL);
|
||||||
fn_info->set_status(SymbolInfo::STATUS_DECLARED);
|
fn_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||||
|
} else if (user_export_addr) {
|
||||||
|
// Rewrite PPC code to set r11 to the target address
|
||||||
|
// So we'll have:
|
||||||
|
// lis r11, user_export_addr
|
||||||
|
// ori r11, r11, user_export_addr
|
||||||
|
// mtspr CTR, r11
|
||||||
|
// bctr
|
||||||
|
uint16_t hi_addr = (user_export_addr >> 16) & 0xFFFF;
|
||||||
|
uint16_t low_addr = user_export_addr & 0xFFFF;
|
||||||
|
|
||||||
|
uint8_t* p = memory()->TranslateVirtual(info->thunk_address);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x0, 0x3D600000 | hi_addr);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x4, 0x616B0000 | low_addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,17 @@
|
||||||
#include "xenia/kernel/util/xex2.h"
|
#include "xenia/kernel/util/xex2.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
|
||||||
|
// KernelState forward decl.
|
||||||
|
namespace kernel { class KernelState; }
|
||||||
|
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
|
|
||||||
class Runtime;
|
class Runtime;
|
||||||
|
|
||||||
class XexModule : public xe::cpu::Module {
|
class XexModule : public xe::cpu::Module {
|
||||||
public:
|
public:
|
||||||
XexModule(Processor* processor);
|
XexModule(Processor* processor, kernel::KernelState* state);
|
||||||
virtual ~XexModule();
|
virtual ~XexModule();
|
||||||
|
|
||||||
xe_xex2_ref xex() const { return xex_; }
|
xe_xex2_ref xex() const { return xex_; }
|
||||||
|
@ -40,6 +44,7 @@ class XexModule : public xe::cpu::Module {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Processor* processor_;
|
Processor* processor_;
|
||||||
|
kernel::KernelState* kernel_state_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
std::string path_;
|
std::string path_;
|
||||||
xe_xex2_ref xex_;
|
xe_xex2_ref xex_;
|
||||||
|
|
|
@ -97,6 +97,19 @@ void KernelState::RegisterModule(XModule* module) {}
|
||||||
|
|
||||||
void KernelState::UnregisterModule(XModule* module) {}
|
void KernelState::UnregisterModule(XModule* module) {}
|
||||||
|
|
||||||
|
bool KernelState::IsKernelModule(const char* name) {
|
||||||
|
if (!name) {
|
||||||
|
// executing module isn't a kernel module
|
||||||
|
return false;
|
||||||
|
} else if (strcasecmp(name, "xam.xex") == 0) {
|
||||||
|
return true;
|
||||||
|
} else if (strcasecmp(name, "xboxkrnl.exe") == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
XModule* KernelState::GetModule(const char* name) {
|
XModule* KernelState::GetModule(const char* name) {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
// NULL name = self.
|
// NULL name = self.
|
||||||
|
@ -114,7 +127,7 @@ XModule* KernelState::GetModule(const char* name) {
|
||||||
// Some games request this, for some reason. wtf.
|
// Some games request this, for some reason. wtf.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
std::lock_guard<std::mutex> lock(object_mutex_);
|
std::lock_guard<std::recursive_mutex> lock(object_mutex_);
|
||||||
|
|
||||||
for (XUserModule* module : user_modules_) {
|
for (XUserModule* module : user_modules_) {
|
||||||
if ((strcasecmp(xe::find_name_from_path(module->path()).c_str(), name) ==
|
if ((strcasecmp(xe::find_name_from_path(module->path()).c_str(), name) ==
|
||||||
|
@ -163,7 +176,7 @@ XUserModule* KernelState::LoadUserModule(const char* raw_name) {
|
||||||
|
|
||||||
XUserModule* module = nullptr;
|
XUserModule* module = nullptr;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(object_mutex_);
|
std::lock_guard<std::recursive_mutex> lock(object_mutex_);
|
||||||
|
|
||||||
// See if we've already loaded it
|
// See if we've already loaded it
|
||||||
for (XUserModule* existing_module : user_modules_) {
|
for (XUserModule* existing_module : user_modules_) {
|
||||||
|
@ -205,12 +218,12 @@ XUserModule* KernelState::LoadUserModule(const char* raw_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelState::RegisterThread(XThread* thread) {
|
void KernelState::RegisterThread(XThread* thread) {
|
||||||
std::lock_guard<std::mutex> lock(object_mutex_);
|
std::lock_guard<std::recursive_mutex> lock(object_mutex_);
|
||||||
threads_by_id_[thread->thread_id()] = thread;
|
threads_by_id_[thread->thread_id()] = thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelState::UnregisterThread(XThread* thread) {
|
void KernelState::UnregisterThread(XThread* thread) {
|
||||||
std::lock_guard<std::mutex> lock(object_mutex_);
|
std::lock_guard<std::recursive_mutex> lock(object_mutex_);
|
||||||
auto it = threads_by_id_.find(thread->thread_id());
|
auto it = threads_by_id_.find(thread->thread_id());
|
||||||
if (it != threads_by_id_.end()) {
|
if (it != threads_by_id_.end()) {
|
||||||
threads_by_id_.erase(it);
|
threads_by_id_.erase(it);
|
||||||
|
@ -218,7 +231,7 @@ void KernelState::UnregisterThread(XThread* thread) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelState::OnThreadExecute(XThread* thread) {
|
void KernelState::OnThreadExecute(XThread* thread) {
|
||||||
std::lock_guard<std::mutex> lock(object_mutex_);
|
std::lock_guard<std::recursive_mutex> lock(object_mutex_);
|
||||||
|
|
||||||
// Must be called on executing thread.
|
// Must be called on executing thread.
|
||||||
assert_true(XThread::GetCurrentThread() == thread);
|
assert_true(XThread::GetCurrentThread() == thread);
|
||||||
|
@ -241,7 +254,7 @@ void KernelState::OnThreadExecute(XThread* thread) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelState::OnThreadExit(XThread* thread) {
|
void KernelState::OnThreadExit(XThread* thread) {
|
||||||
std::lock_guard<std::mutex> lock(object_mutex_);
|
std::lock_guard<std::recursive_mutex> lock(object_mutex_);
|
||||||
|
|
||||||
// Must be called on executing thread.
|
// Must be called on executing thread.
|
||||||
assert_true(XThread::GetCurrentThread() == thread);
|
assert_true(XThread::GetCurrentThread() == thread);
|
||||||
|
@ -264,7 +277,7 @@ void KernelState::OnThreadExit(XThread* thread) {
|
||||||
}
|
}
|
||||||
|
|
||||||
XThread* KernelState::GetThreadByID(uint32_t thread_id) {
|
XThread* KernelState::GetThreadByID(uint32_t thread_id) {
|
||||||
std::lock_guard<std::mutex> lock(object_mutex_);
|
std::lock_guard<std::recursive_mutex> lock(object_mutex_);
|
||||||
XThread* thread = nullptr;
|
XThread* thread = nullptr;
|
||||||
auto it = threads_by_id_.find(thread_id);
|
auto it = threads_by_id_.find(thread_id);
|
||||||
if (it != threads_by_id_.end()) {
|
if (it != threads_by_id_.end()) {
|
||||||
|
@ -276,7 +289,7 @@ XThread* KernelState::GetThreadByID(uint32_t thread_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelState::RegisterNotifyListener(XNotifyListener* listener) {
|
void KernelState::RegisterNotifyListener(XNotifyListener* listener) {
|
||||||
std::lock_guard<std::mutex> lock(object_mutex_);
|
std::lock_guard<std::recursive_mutex> lock(object_mutex_);
|
||||||
notify_listeners_.push_back(listener);
|
notify_listeners_.push_back(listener);
|
||||||
|
|
||||||
// Games seem to expect a few notifications on startup, only for the first
|
// Games seem to expect a few notifications on startup, only for the first
|
||||||
|
@ -300,7 +313,7 @@ void KernelState::RegisterNotifyListener(XNotifyListener* listener) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelState::UnregisterNotifyListener(XNotifyListener* listener) {
|
void KernelState::UnregisterNotifyListener(XNotifyListener* listener) {
|
||||||
std::lock_guard<std::mutex> lock(object_mutex_);
|
std::lock_guard<std::recursive_mutex> lock(object_mutex_);
|
||||||
for (auto it = notify_listeners_.begin(); it != notify_listeners_.end();
|
for (auto it = notify_listeners_.begin(); it != notify_listeners_.end();
|
||||||
++it) {
|
++it) {
|
||||||
if (*it == listener) {
|
if (*it == listener) {
|
||||||
|
@ -311,7 +324,7 @@ void KernelState::UnregisterNotifyListener(XNotifyListener* listener) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelState::BroadcastNotification(XNotificationID id, uint32_t data) {
|
void KernelState::BroadcastNotification(XNotificationID id, uint32_t data) {
|
||||||
std::lock_guard<std::mutex> lock(object_mutex_);
|
std::lock_guard<std::recursive_mutex> lock(object_mutex_);
|
||||||
for (auto it = notify_listeners_.begin(); it != notify_listeners_.end();
|
for (auto it = notify_listeners_.begin(); it != notify_listeners_.end();
|
||||||
++it) {
|
++it) {
|
||||||
(*it)->EnqueueNotification(id, data);
|
(*it)->EnqueueNotification(id, data);
|
||||||
|
|
|
@ -63,13 +63,14 @@ class KernelState {
|
||||||
ContentManager* content_manager() const { return content_manager_.get(); }
|
ContentManager* content_manager() const { return content_manager_.get(); }
|
||||||
|
|
||||||
ObjectTable* object_table() const { return object_table_; }
|
ObjectTable* object_table() const { return object_table_; }
|
||||||
std::mutex& object_mutex() { return object_mutex_; }
|
std::recursive_mutex& object_mutex() { return object_mutex_; }
|
||||||
|
|
||||||
uint32_t process_type() const { return process_type_; }
|
uint32_t process_type() const { return process_type_; }
|
||||||
void set_process_type(uint32_t value) { process_type_ = value; }
|
void set_process_type(uint32_t value) { process_type_ = value; }
|
||||||
|
|
||||||
void RegisterModule(XModule* module);
|
void RegisterModule(XModule* module);
|
||||||
void UnregisterModule(XModule* module);
|
void UnregisterModule(XModule* module);
|
||||||
|
bool IsKernelModule(const char* name);
|
||||||
XModule* GetModule(const char* name);
|
XModule* GetModule(const char* name);
|
||||||
XUserModule* GetExecutableModule();
|
XUserModule* GetExecutableModule();
|
||||||
void SetExecutableModule(XUserModule* module);
|
void SetExecutableModule(XUserModule* module);
|
||||||
|
@ -105,7 +106,7 @@ class KernelState {
|
||||||
std::unique_ptr<ContentManager> content_manager_;
|
std::unique_ptr<ContentManager> content_manager_;
|
||||||
|
|
||||||
ObjectTable* object_table_;
|
ObjectTable* object_table_;
|
||||||
std::mutex object_mutex_;
|
std::recursive_mutex object_mutex_;
|
||||||
std::unordered_map<uint32_t, XThread*> threads_by_id_;
|
std::unordered_map<uint32_t, XThread*> threads_by_id_;
|
||||||
std::vector<XNotifyListener*> notify_listeners_;
|
std::vector<XNotifyListener*> notify_listeners_;
|
||||||
bool has_notified_startup_;
|
bool has_notified_startup_;
|
||||||
|
|
|
@ -129,7 +129,7 @@ X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) {
|
||||||
|
|
||||||
// Prepare the module for execution.
|
// Prepare the module for execution.
|
||||||
// Runtime takes ownership.
|
// Runtime takes ownership.
|
||||||
auto xex_module = std::make_unique<XexModule>(processor);
|
auto xex_module = std::make_unique<XexModule>(processor, kernel_state());
|
||||||
if (!xex_module->Load(name_, path_, xex_)) {
|
if (!xex_module->Load(name_, path_, xex_)) {
|
||||||
return X_STATUS_UNSUCCESSFUL;
|
return X_STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
@ -351,6 +351,8 @@ void XUserModule::Dump() {
|
||||||
int unimpl_count = 0;
|
int unimpl_count = 0;
|
||||||
for (size_t m = 0; m < import_info_count; m++) {
|
for (size_t m = 0; m < import_info_count; m++) {
|
||||||
const xe_xex2_import_info_t* info = &import_infos[m];
|
const xe_xex2_import_info_t* info = &import_infos[m];
|
||||||
|
|
||||||
|
if (kernel_state_->IsKernelModule(library->name)) {
|
||||||
KernelExport* kernel_export =
|
KernelExport* kernel_export =
|
||||||
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
||||||
if (kernel_export) {
|
if (kernel_export) {
|
||||||
|
@ -364,6 +366,24 @@ void XUserModule::Dump() {
|
||||||
unknown_count++;
|
unknown_count++;
|
||||||
unimpl_count++;
|
unimpl_count++;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// User module
|
||||||
|
XModule* module = kernel_state_->GetModule(library->name);
|
||||||
|
if (module) {
|
||||||
|
uint32_t export_addr =
|
||||||
|
module->GetProcAddressByOrdinal(info->ordinal);
|
||||||
|
if (export_addr) {
|
||||||
|
impl_count++;
|
||||||
|
known_count++;
|
||||||
|
} else {
|
||||||
|
unimpl_count++;
|
||||||
|
unknown_count++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unimpl_count++;
|
||||||
|
unknown_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printf(" Total: %4u\n", uint32_t(import_info_count));
|
printf(" Total: %4u\n", uint32_t(import_info_count));
|
||||||
printf(" Known: %3d%% (%d known, %d unknown)\n",
|
printf(" Known: %3d%% (%d known, %d unknown)\n",
|
||||||
|
@ -377,14 +397,24 @@ void XUserModule::Dump() {
|
||||||
// Listing.
|
// Listing.
|
||||||
for (size_t m = 0; m < import_info_count; m++) {
|
for (size_t m = 0; m < import_info_count; m++) {
|
||||||
const xe_xex2_import_info_t* info = &import_infos[m];
|
const xe_xex2_import_info_t* info = &import_infos[m];
|
||||||
KernelExport* kernel_export =
|
|
||||||
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
|
||||||
const char* name = "UNKNOWN";
|
const char* name = "UNKNOWN";
|
||||||
bool implemented = false;
|
bool implemented = false;
|
||||||
|
|
||||||
|
KernelExport* kernel_export;
|
||||||
|
if (kernel_state_->IsKernelModule(library->name)) {
|
||||||
|
kernel_export =
|
||||||
|
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
||||||
if (kernel_export) {
|
if (kernel_export) {
|
||||||
name = kernel_export->name;
|
name = kernel_export->name;
|
||||||
implemented = kernel_export->is_implemented;
|
implemented = kernel_export->is_implemented;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
XModule* module = kernel_state_->GetModule(library->name);
|
||||||
|
if (module && module->GetProcAddressByOrdinal(info->ordinal)) {
|
||||||
|
// TODO: Name lookup
|
||||||
|
implemented = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (kernel_export && kernel_export->type == KernelExport::Variable) {
|
if (kernel_export && kernel_export->type == KernelExport::Variable) {
|
||||||
printf(" V %.8X %.3X (%3d) %s %s\n", info->value_address,
|
printf(" V %.8X %.3X (%3d) %s %s\n", info->value_address,
|
||||||
info->ordinal, info->ordinal, implemented ? " " : "!!", name);
|
info->ordinal, info->ordinal, implemented ? " " : "!!", name);
|
||||||
|
|
|
@ -610,8 +610,8 @@ int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
uint8_t *buffer = memory->TranslateVirtual(header->exe_address);
|
uint8_t *buffer = memory->TranslateVirtual(header->exe_address);
|
||||||
|
std::memset(buffer, 0, total_size); // Quickly zero the contents.
|
||||||
uint8_t *d = buffer;
|
uint8_t *d = buffer;
|
||||||
std::memset(buffer, 0, uncompressed_size);
|
|
||||||
|
|
||||||
uint32_t rk[4 * (MAXNR + 1)];
|
uint32_t rk[4 * (MAXNR + 1)];
|
||||||
uint8_t ivec[16] = {0};
|
uint8_t ivec[16] = {0};
|
||||||
|
|
|
@ -153,7 +153,7 @@ X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
|
||||||
}
|
}
|
||||||
|
|
||||||
void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) {
|
void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) {
|
||||||
std::lock_guard<std::mutex> lock(kernel_state_->object_mutex());
|
std::lock_guard<std::recursive_mutex> lock(kernel_state_->object_mutex());
|
||||||
|
|
||||||
auto header =
|
auto header =
|
||||||
kernel_state_->memory()->TranslateVirtual<DISPATCH_HEADER*>(native_ptr);
|
kernel_state_->memory()->TranslateVirtual<DISPATCH_HEADER*>(native_ptr);
|
||||||
|
@ -181,7 +181,7 @@ XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
|
||||||
// We identify this by checking the low bit of wait_list_blink - if it's 1,
|
// We identify this by checking the low bit of wait_list_blink - if it's 1,
|
||||||
// we have already put our pointer in there.
|
// we have already put our pointer in there.
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(kernel_state->object_mutex());
|
std::lock_guard<std::recursive_mutex> lock(kernel_state->object_mutex());
|
||||||
|
|
||||||
auto header = reinterpret_cast<DISPATCH_HEADER*>(native_ptr);
|
auto header = reinterpret_cast<DISPATCH_HEADER*>(native_ptr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue