Directly check PEB for IsDebuggerAttached
Add constexpr getters to magicdiv class so it can be used from jitted x64/dxbc Track the guest return address as well for guest/host sync, if multiple entries have the same guest stack find the first one with a matching guest retaddr. this fixes epic mickey 2 (which the previous guest-stack change had allowed to go ingame for a bit) and potentially also a crash in fable3. Break if under debugger when stackpoints are overflowed Add much more useful output for host exceptions, print out xenia_canary.exe relative offsets if exception is in module, formatmessage for ntstatus/win32err, strerror Minor d3d12 microoptimization, instead of doing SetEventOnCompletion + WaitForSingleObject do SetEventOnCompletion w/ nullptr so that the wait happens in kernel mode, avoiding two extra context switches add unimplemented kernel functions: ExAllocatePoolWithTag ObReferenceObject ObDereferenceObject has no return value. Log a message when ObDereferenceObject/Reference receive unregistered guest kernel objects gave ObLookupThreadByThreadId its correct error status hoist object_types initialization out of ObReferenceObjectByHandle Fix out parameter values on error for a few kernel funcs add note about msr to KeSetCurrentStackPointers add X_STATUS_OBJECT_TYPE_MISMATCH check for xeNtSetEvent add msr_mask field to X_KPCR
This commit is contained in:
@@ -37,14 +37,30 @@ struct XTASK_MESSAGE {
|
||||
be<uint32_t> unknown_14;
|
||||
be<uint32_t> task_handle;
|
||||
};
|
||||
|
||||
struct XAM_TASK_ARGS {
|
||||
be<uint32_t> value1;
|
||||
be<uint32_t> value2;
|
||||
// i think there might be another value here, it might be padding
|
||||
};
|
||||
static_assert_size(XTASK_MESSAGE, 0x1C);
|
||||
|
||||
dword_result_t XamTaskSchedule_entry(lpvoid_t callback,
|
||||
pointer_t<XTASK_MESSAGE> message,
|
||||
lpdword_t unknown, lpdword_t handle_ptr) {
|
||||
dword_t optional_ptr, lpdword_t handle_ptr,
|
||||
const ppc_context_t& ctx) {
|
||||
// TODO(gibbed): figure out what this is for
|
||||
*handle_ptr = 12345;
|
||||
|
||||
if (optional_ptr) {
|
||||
auto option = ctx->TranslateVirtual<XAM_TASK_ARGS*>(optional_ptr);
|
||||
|
||||
auto v1 = option->value1;
|
||||
auto v2 = option->value2; //typically 0?
|
||||
|
||||
XELOGI("Got xam task args: v1 = {:08X}, v2 = {:08X}", v1, v2);
|
||||
}
|
||||
|
||||
uint32_t stack_size = kernel_state()->GetExecutableModule()->stack_size();
|
||||
|
||||
// Stack must be aligned to 16kb pages
|
||||
|
||||
@@ -609,6 +609,10 @@ dword_result_t ExAllocatePoolTypeWithTag_entry(dword_t size, dword_t tag,
|
||||
return addr;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ExAllocatePoolTypeWithTag, kMemory, kImplemented);
|
||||
dword_result_t ExAllocatePoolWithTag_entry(dword_t numbytes, dword_t tag) {
|
||||
return ExAllocatePoolTypeWithTag_entry(numbytes, tag, 0);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ExAllocatePoolWithTag, kMemory, kImplemented);
|
||||
|
||||
dword_result_t ExAllocatePool_entry(dword_t size) {
|
||||
const uint32_t none = 0x656E6F4E; // 'None'
|
||||
|
||||
@@ -52,9 +52,11 @@ dword_result_t ObOpenObjectByName_entry(lpunknown_t obj_attributes_ptr,
|
||||
return result;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ObOpenObjectByName, kNone, kImplemented);
|
||||
|
||||
// chrispy: investigate this, pretty certain it does not properly emulate the
|
||||
// original
|
||||
dword_result_t ObOpenObjectByPointer_entry(lpvoid_t object_ptr,
|
||||
lpdword_t out_handle_ptr) {
|
||||
*out_handle_ptr = 0;
|
||||
auto object = XObject::GetNativeObject<XObject>(kernel_state(), object_ptr);
|
||||
if (!object) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
@@ -71,7 +73,8 @@ dword_result_t ObLookupThreadByThreadId_entry(dword_t thread_id,
|
||||
lpdword_t out_object_ptr) {
|
||||
auto thread = kernel_state()->GetThreadByID(thread_id);
|
||||
if (!thread) {
|
||||
return X_STATUS_NOT_FOUND;
|
||||
*out_object_ptr = 0;
|
||||
return X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Retain the object. Will be released in ObDereferenceObject.
|
||||
@@ -80,16 +83,18 @@ dword_result_t ObLookupThreadByThreadId_entry(dword_t thread_id,
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ObLookupThreadByThreadId, kNone, kImplemented);
|
||||
|
||||
// These values come from how Xenia handles uninitialized kernel data exports.
|
||||
// D###BEEF where ### is the ordinal.
|
||||
const static std::unordered_map<XObject::Type, uint32_t> object_types = {
|
||||
{XObject::Type::Event, 0xD00EBEEF},
|
||||
{XObject::Type::Semaphore, 0xD017BEEF},
|
||||
{XObject::Type::Thread, 0xD01BBEEF}};
|
||||
dword_result_t ObReferenceObjectByHandle_entry(dword_t handle,
|
||||
dword_t object_type_ptr,
|
||||
lpdword_t out_object_ptr) {
|
||||
// These values come from how Xenia handles uninitialized kernel data exports.
|
||||
// D###BEEF where ### is the ordinal.
|
||||
const static std::unordered_map<XObject::Type, uint32_t> object_types = {
|
||||
{XObject::Type::Event, 0xD00EBEEF},
|
||||
{XObject::Type::Semaphore, 0xD017BEEF},
|
||||
{XObject::Type::Thread, 0xD01BBEEF}};
|
||||
// chrispy: gotta preinit this to 0, kernel is expected to do that
|
||||
*out_object_ptr = 0;
|
||||
|
||||
auto object = kernel_state()->object_table()->LookupObject<XObject>(handle);
|
||||
if (!object) {
|
||||
return X_STATUS_INVALID_HANDLE;
|
||||
@@ -132,22 +137,43 @@ dword_result_t ObReferenceObjectByName_entry(lpstring_t name,
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ObReferenceObjectByName, kNone, kImplemented);
|
||||
|
||||
dword_result_t ObDereferenceObject_entry(dword_t native_ptr) {
|
||||
void ObDereferenceObject_entry(dword_t native_ptr, const ppc_context_t& ctx) {
|
||||
// Check if a dummy value from ObReferenceObjectByHandle.
|
||||
if (native_ptr == 0xDEADF00D) {
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
auto object = XObject::GetNativeObject<XObject>(
|
||||
kernel_state(), kernel_memory()->TranslateVirtual(native_ptr));
|
||||
if (object) {
|
||||
object->ReleaseHandle();
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
if (native_ptr) {
|
||||
XELOGW("Unregistered guest object provided to ObDereferenceObject {:08X}",
|
||||
native_ptr.value());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ObDereferenceObject, kNone, kImplemented);
|
||||
|
||||
void ObReferenceObject_entry(dword_t native_ptr) {
|
||||
// Check if a dummy value from ObReferenceObjectByHandle.
|
||||
auto object = XObject::GetNativeObject<XObject>(
|
||||
kernel_state(), kernel_memory()->TranslateVirtual(native_ptr));
|
||||
if (object) {
|
||||
object->RetainHandle();
|
||||
} else {
|
||||
if (native_ptr) {
|
||||
XELOGW("Unregistered guest object provided to ObReferenceObject {:08X}",
|
||||
native_ptr.value());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ObReferenceObject, kNone, kImplemented);
|
||||
|
||||
dword_result_t ObCreateSymbolicLink_entry(pointer_t<X_ANSI_STRING> path_ptr,
|
||||
pointer_t<X_ANSI_STRING> target_ptr) {
|
||||
auto path = xe::utf8::canonicalize_guest_path(
|
||||
|
||||
@@ -237,7 +237,7 @@ void KeSetCurrentStackPointers_entry(lpvoid_t stack_ptr,
|
||||
auto current_thread = XThread::GetCurrentThread();
|
||||
|
||||
auto pcr = context->TranslateVirtualGPR<X_KPCR*>(context->r[13]);
|
||||
|
||||
//also supposed to load msr mask, and the current msr with that, and store
|
||||
thread->stack_alloc_base = stack_alloc_base.value();
|
||||
thread->stack_base = stack_base.value();
|
||||
thread->stack_limit = stack_limit.value();
|
||||
@@ -500,6 +500,10 @@ uint32_t xeNtSetEvent(uint32_t handle, xe::be<uint32_t>* previous_state_ptr) {
|
||||
|
||||
auto ev = kernel_state()->object_table()->LookupObject<XEvent>(handle);
|
||||
if (ev) {
|
||||
//d3 ros does this
|
||||
if (ev->type() != XObject::Type::Event) {
|
||||
return X_STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
int32_t was_signalled = ev->Set(0, false);
|
||||
if (previous_state_ptr) {
|
||||
*previous_state_ptr = static_cast<uint32_t>(was_signalled);
|
||||
|
||||
@@ -70,7 +70,8 @@ struct XAPC {
|
||||
// Processor Control Region
|
||||
struct X_KPCR {
|
||||
xe::be<uint32_t> tls_ptr; // 0x0
|
||||
uint8_t unk_04[0x2C]; // 0x4
|
||||
xe::be<uint32_t> msr_mask; // 0x4
|
||||
uint8_t unk_08[0x28]; // 0x8
|
||||
xe::be<uint32_t> pcr_ptr; // 0x30
|
||||
uint8_t unk_34[0x3C]; // 0x34
|
||||
xe::be<uint32_t> stack_base_ptr; // 0x70 Stack base address (high addr)
|
||||
|
||||
Reference in New Issue
Block a user