mirror of
https://github.com/xenia-project/xenia.git
synced 2025-12-06 07:12:03 +01:00
XObject CreateNative
This commit is contained in:
parent
a0a8b7ec37
commit
bdcadeffe5
|
|
@ -144,17 +144,13 @@ uint8_t GetFakeCpuNumber(uint8_t proc_mask) {
|
||||||
|
|
||||||
X_STATUS XThread::Create() {
|
X_STATUS XThread::Create() {
|
||||||
// Thread kernel object
|
// Thread kernel object
|
||||||
// TODO: This is supposed to be preceded by X_OBJECT_HEADER, need to see if
|
// This call will also setup the native pointer for us.
|
||||||
// that's absolutely necessary.
|
uint8_t* guest_object = CreateNative(sizeof(X_THREAD));
|
||||||
thread_object_address_ = memory()->SystemHeapAlloc(sizeof(X_THREAD));
|
if (!guest_object) {
|
||||||
if (!thread_object_address_) {
|
|
||||||
XELOGW("Unable to allocate thread object");
|
XELOGW("Unable to allocate thread object");
|
||||||
return X_STATUS_NO_MEMORY;
|
return X_STATUS_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set native info.
|
|
||||||
SetNativePointer(thread_object_address_, true);
|
|
||||||
|
|
||||||
// Allocate thread state block from heap.
|
// Allocate thread state block from heap.
|
||||||
// This is set as r13 for user code and some special inlined Win32 calls
|
// This is set as r13 for user code and some special inlined Win32 calls
|
||||||
// (like GetLastError/etc) will poke it directly.
|
// (like GetLastError/etc) will poke it directly.
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ class XThread : public XObject {
|
||||||
|
|
||||||
uint32_t pcr_ptr() const { return pcr_address_; }
|
uint32_t pcr_ptr() const { return pcr_address_; }
|
||||||
uint32_t thread_state_ptr() const { return thread_state_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_; }
|
cpu::ThreadState* thread_state() const { return thread_state_; }
|
||||||
uint32_t thread_id() const { return thread_id_; }
|
uint32_t thread_id() const { return thread_id_; }
|
||||||
|
|
@ -148,7 +147,6 @@ class XThread : public XObject {
|
||||||
uint32_t tls_address_;
|
uint32_t tls_address_;
|
||||||
uint32_t pcr_address_;
|
uint32_t pcr_address_;
|
||||||
uint32_t thread_state_address_;
|
uint32_t thread_state_address_;
|
||||||
uint32_t thread_object_address_; // Kernel object
|
|
||||||
cpu::ThreadState* thread_state_;
|
cpu::ThreadState* thread_state_;
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ SHIM_CALL ObReferenceObjectByHandle_shim(PPCContext* ppc_context,
|
||||||
} break;*/
|
} break;*/
|
||||||
case XObject::kTypeThread: {
|
case XObject::kTypeThread: {
|
||||||
auto thread = object.get<XThread>();
|
auto thread = object.get<XThread>();
|
||||||
native_ptr = thread->object_ptr();
|
native_ptr = thread->guest_object();
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
assert_unhandled_case(object->type());
|
assert_unhandled_case(object->type());
|
||||||
|
|
@ -89,6 +89,8 @@ SHIM_CALL ObReferenceObjectByHandle_shim(PPCContext* ppc_context,
|
||||||
assert(object->type() == XObject::kTypeSemaphore);
|
assert(object->type() == XObject::kTypeSemaphore);
|
||||||
auto sem = object.get<XSemaphore>();
|
auto sem = object.get<XSemaphore>();
|
||||||
|
|
||||||
|
native_ptr = sem->guest_object();
|
||||||
|
|
||||||
// TODO(benvanik): implement.
|
// TODO(benvanik): implement.
|
||||||
assert_unhandled_case(object_type_ptr);
|
assert_unhandled_case(object_type_ptr);
|
||||||
native_ptr = 0xDEADF00D;
|
native_ptr = 0xDEADF00D;
|
||||||
|
|
@ -97,7 +99,7 @@ SHIM_CALL ObReferenceObjectByHandle_shim(PPCContext* ppc_context,
|
||||||
assert(object->type() == XObject::kTypeThread);
|
assert(object->type() == XObject::kTypeThread);
|
||||||
auto thread = object.get<XThread>();
|
auto thread = object.get<XThread>();
|
||||||
|
|
||||||
native_ptr = thread->object_ptr();
|
native_ptr = thread->guest_object();
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
assert_unhandled_case(object_type_ptr);
|
assert_unhandled_case(object_type_ptr);
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@ XObject::XObject(KernelState* kernel_state, Type type)
|
||||||
handle_ref_count_(0),
|
handle_ref_count_(0),
|
||||||
pointer_ref_count_(1),
|
pointer_ref_count_(1),
|
||||||
type_(type),
|
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
|
// Added pointer check to support usage without a kernel_state
|
||||||
if (kernel_state != nullptr) {
|
if (kernel_state != nullptr) {
|
||||||
kernel_state->object_table()->AddHandle(this, &handle_);
|
kernel_state->object_table()->AddHandle(this, &handle_);
|
||||||
|
|
@ -34,6 +36,11 @@ XObject::XObject(KernelState* kernel_state, Type type)
|
||||||
XObject::~XObject() {
|
XObject::~XObject() {
|
||||||
assert_zero(handle_ref_count_);
|
assert_zero(handle_ref_count_);
|
||||||
assert_zero(pointer_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_; }
|
Emulator* XObject::emulator() const { return kernel_state_->emulator_; }
|
||||||
|
|
@ -161,6 +168,38 @@ X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t* XObject::CreateNative(uint32_t size) {
|
||||||
|
std::lock_guard<xe::recursive_mutex> 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<X_OBJECT_HEADER*>(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) {
|
void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) {
|
||||||
std::lock_guard<xe::recursive_mutex> lock(kernel_state_->object_mutex());
|
std::lock_guard<xe::recursive_mutex> lock(kernel_state_->object_mutex());
|
||||||
|
|
||||||
|
|
@ -173,6 +212,7 @@ void XObject::SetNativePointer(uint32_t native_ptr, bool uninitialized) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stash pointer in struct.
|
// Stash pointer in struct.
|
||||||
|
// FIXME: This assumes the object has a dispatch header (some don't!)
|
||||||
uint64_t object_ptr = reinterpret_cast<uint64_t>(this);
|
uint64_t object_ptr = reinterpret_cast<uint64_t>(this);
|
||||||
object_ptr |= 0x1;
|
object_ptr |= 0x1;
|
||||||
header->wait_list_flink = (uint32_t)(object_ptr >> 32);
|
header->wait_list_flink = (uint32_t)(object_ptr >> 32);
|
||||||
|
|
@ -251,6 +291,7 @@ object_ref<XObject> XObject::GetNativeObject(KernelState* kernel_state,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stash pointer in struct.
|
// Stash pointer in struct.
|
||||||
|
// FIXME: This assumes the object contains a dispatch header (some don't!)
|
||||||
uint64_t object_ptr = reinterpret_cast<uint64_t>(object);
|
uint64_t object_ptr = reinterpret_cast<uint64_t>(object);
|
||||||
object_ptr |= 0x1;
|
object_ptr |= 0x1;
|
||||||
header->wait_list_flink = (uint32_t)(object_ptr >> 32);
|
header->wait_list_flink = (uint32_t)(object_ptr >> 32);
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ struct X_OBJECT_HEADER {
|
||||||
// (There's actually a body field here which is the object itself)
|
// (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 {
|
struct X_OBJECT_CREATE_INFORMATION {
|
||||||
xe::be<uint32_t> attributes;
|
xe::be<uint32_t> attributes;
|
||||||
xe::be<uint32_t> root_directory_ptr;
|
xe::be<uint32_t> root_directory_ptr;
|
||||||
|
|
@ -114,6 +115,7 @@ class XObject {
|
||||||
Type type();
|
Type type();
|
||||||
X_HANDLE handle() const;
|
X_HANDLE handle() const;
|
||||||
const std::string& name() const { return name_; }
|
const std::string& name() const { return name_; }
|
||||||
|
uint32_t guest_object() const { return guest_object_ptr_; }
|
||||||
|
|
||||||
void RetainHandle();
|
void RetainHandle();
|
||||||
bool ReleaseHandle();
|
bool ReleaseHandle();
|
||||||
|
|
@ -149,6 +151,8 @@ class XObject {
|
||||||
virtual void* GetWaitHandle() { return 0; }
|
virtual void* GetWaitHandle() { return 0; }
|
||||||
|
|
||||||
protected:
|
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);
|
void SetNativePointer(uint32_t native_ptr, bool uninitialized = false);
|
||||||
|
|
||||||
static uint32_t TimeoutTicksToMs(int64_t timeout_ticks);
|
static uint32_t TimeoutTicksToMs(int64_t timeout_ticks);
|
||||||
|
|
@ -162,6 +166,11 @@ class XObject {
|
||||||
Type type_;
|
Type type_;
|
||||||
X_HANDLE handle_;
|
X_HANDLE handle_;
|
||||||
std::string name_; // May be zero length.
|
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 <typename T>
|
template <typename T>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue