From bdcadeffe584f680385d8031470c58611cb73b96 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Fri, 12 Jun 2015 20:09:47 -0500 Subject: [PATCH] XObject CreateNative --- src/xenia/kernel/objects/xthread.cc | 10 ++----- src/xenia/kernel/objects/xthread.h | 2 -- src/xenia/kernel/xboxkrnl_ob.cc | 6 ++-- src/xenia/kernel/xobject.cc | 43 ++++++++++++++++++++++++++++- src/xenia/kernel/xobject.h | 9 ++++++ 5 files changed, 58 insertions(+), 12 deletions(-) diff --git a/src/xenia/kernel/objects/xthread.cc b/src/xenia/kernel/objects/xthread.cc index 720e28489..6192a3456 100644 --- a/src/xenia/kernel/objects/xthread.cc +++ b/src/xenia/kernel/objects/xthread.cc @@ -144,17 +144,13 @@ uint8_t GetFakeCpuNumber(uint8_t proc_mask) { X_STATUS XThread::Create() { // Thread kernel object - // TODO: This is supposed to be preceded by X_OBJECT_HEADER, need to see if - // that's absolutely necessary. - thread_object_address_ = memory()->SystemHeapAlloc(sizeof(X_THREAD)); - if (!thread_object_address_) { + // This call will also setup the native pointer for us. + uint8_t* guest_object = CreateNative(sizeof(X_THREAD)); + if (!guest_object) { XELOGW("Unable to allocate thread object"); return X_STATUS_NO_MEMORY; } - // Set native info. - SetNativePointer(thread_object_address_, true); - // Allocate thread state block from heap. // This is set as r13 for user code and some special inlined Win32 calls // (like GetLastError/etc) will poke it directly. diff --git a/src/xenia/kernel/objects/xthread.h b/src/xenia/kernel/objects/xthread.h index ea2cd9cd7..a97d85182 100644 --- a/src/xenia/kernel/objects/xthread.h +++ b/src/xenia/kernel/objects/xthread.h @@ -87,7 +87,6 @@ class XThread : public XObject { uint32_t pcr_ptr() const { return pcr_address_; } uint32_t thread_state_ptr() const { return thread_state_address_; } - uint32_t object_ptr() const { return thread_object_address_; } cpu::ThreadState* thread_state() const { return thread_state_; } uint32_t thread_id() const { return thread_id_; } @@ -148,7 +147,6 @@ class XThread : public XObject { uint32_t tls_address_; uint32_t pcr_address_; uint32_t thread_state_address_; - uint32_t thread_object_address_; // Kernel object cpu::ThreadState* thread_state_; std::string name_; diff --git a/src/xenia/kernel/xboxkrnl_ob.cc b/src/xenia/kernel/xboxkrnl_ob.cc index 3a082132c..65f8a8f4e 100644 --- a/src/xenia/kernel/xboxkrnl_ob.cc +++ b/src/xenia/kernel/xboxkrnl_ob.cc @@ -77,7 +77,7 @@ SHIM_CALL ObReferenceObjectByHandle_shim(PPCContext* ppc_context, } break;*/ case XObject::kTypeThread: { auto thread = object.get(); - native_ptr = thread->object_ptr(); + native_ptr = thread->guest_object(); } break; default: { assert_unhandled_case(object->type()); @@ -89,6 +89,8 @@ SHIM_CALL ObReferenceObjectByHandle_shim(PPCContext* ppc_context, assert(object->type() == XObject::kTypeSemaphore); auto sem = object.get(); + native_ptr = sem->guest_object(); + // TODO(benvanik): implement. assert_unhandled_case(object_type_ptr); native_ptr = 0xDEADF00D; @@ -97,7 +99,7 @@ SHIM_CALL ObReferenceObjectByHandle_shim(PPCContext* ppc_context, assert(object->type() == XObject::kTypeThread); auto thread = object.get(); - native_ptr = thread->object_ptr(); + native_ptr = thread->guest_object(); } break; default: { assert_unhandled_case(object_type_ptr); diff --git a/src/xenia/kernel/xobject.cc b/src/xenia/kernel/xobject.cc index ffb409ef2..e65d979e4 100644 --- a/src/xenia/kernel/xobject.cc +++ b/src/xenia/kernel/xobject.cc @@ -24,7 +24,9 @@ XObject::XObject(KernelState* kernel_state, Type type) handle_ref_count_(0), pointer_ref_count_(1), type_(type), - handle_(X_INVALID_HANDLE_VALUE) { + handle_(X_INVALID_HANDLE_VALUE), + guest_object_ptr_(0), + allocated_guest_object_(false) { // Added pointer check to support usage without a kernel_state if (kernel_state != nullptr) { kernel_state->object_table()->AddHandle(this, &handle_); @@ -34,6 +36,11 @@ XObject::XObject(KernelState* kernel_state, Type type) XObject::~XObject() { assert_zero(handle_ref_count_); assert_zero(pointer_ref_count_); + + if (allocated_guest_object_) { + uint32_t ptr = guest_object_ptr_ - sizeof(X_OBJECT_HEADER); + memory()->SystemHeapFree(ptr); + } } Emulator* XObject::emulator() const { return kernel_state_->emulator_; } @@ -161,6 +168,38 @@ X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects, return result; } +uint8_t* XObject::CreateNative(uint32_t size) { + std::lock_guard lock(kernel_state_->object_mutex()); + + uint32_t total_size = size + sizeof(X_OBJECT_HEADER); + + auto mem = memory()->SystemHeapAlloc(total_size); + if (!mem) { + // Out of memory! + return nullptr; + } + + allocated_guest_object_ = true; + memory()->Zero(mem, total_size); + guest_object_ptr_ = mem + sizeof(X_OBJECT_HEADER); + SetNativePointer(guest_object_ptr_, true); + + auto header = memory()->TranslateVirtual(mem); + + auto creation_info = + memory()->SystemHeapAlloc(sizeof(X_OBJECT_CREATE_INFORMATION)); + if (creation_info) { + memory()->Zero(creation_info, sizeof(X_OBJECT_CREATE_INFORMATION)); + + // Set it up in the header. + // Some kernel method is accessing this struct and dereferencing a member. + // With our current definition that member is non_paged_pool_charge. + header->object_create_info = creation_info; + } + + return memory()->TranslateVirtual(guest_object_ptr_); +} + void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) { std::lock_guard lock(kernel_state_->object_mutex()); @@ -173,6 +212,7 @@ void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) { } // Stash pointer in struct. + // FIXME: This assumes the object has a dispatch header (some don't!) uint64_t object_ptr = reinterpret_cast(this); object_ptr |= 0x1; header->wait_list_flink = (uint32_t)(object_ptr >> 32); @@ -251,6 +291,7 @@ object_ref XObject::GetNativeObject(KernelState* kernel_state, } // Stash pointer in struct. + // FIXME: This assumes the object contains a dispatch header (some don't!) uint64_t object_ptr = reinterpret_cast(object); object_ptr |= 0x1; header->wait_list_flink = (uint32_t)(object_ptr >> 32); diff --git a/src/xenia/kernel/xobject.h b/src/xenia/kernel/xobject.h index 2a6fd5049..e2a12119c 100644 --- a/src/xenia/kernel/xobject.h +++ b/src/xenia/kernel/xobject.h @@ -76,6 +76,7 @@ struct X_OBJECT_HEADER { // (There's actually a body field here which is the object itself) }; +// http://www.nirsoft.net/kernel_struct/vista/OBJECT_CREATE_INFORMATION.html struct X_OBJECT_CREATE_INFORMATION { xe::be attributes; xe::be root_directory_ptr; @@ -114,6 +115,7 @@ class XObject { Type type(); X_HANDLE handle() const; const std::string& name() const { return name_; } + uint32_t guest_object() const { return guest_object_ptr_; } void RetainHandle(); bool ReleaseHandle(); @@ -149,6 +151,8 @@ class XObject { virtual void* GetWaitHandle() { return 0; } protected: + // Creates the kernel object for guest code to use. Typically not needed. + uint8_t* CreateNative(uint32_t size); void SetNativePointer(uint32_t native_ptr, bool uninitialized = false); static uint32_t TimeoutTicksToMs(int64_t timeout_ticks); @@ -162,6 +166,11 @@ class XObject { Type type_; X_HANDLE handle_; std::string name_; // May be zero length. + + // Guest pointer for kernel object. Remember: X_OBJECT_HEADER precedes this + // if we allocated it! + uint32_t guest_object_ptr_; + bool allocated_guest_object_; }; template