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:
chss95cs@gmail.com
2022-12-04 12:38:19 -08:00
parent 1eb61aa9ab
commit a63f424c0a
18 changed files with 412 additions and 105 deletions

View File

@@ -486,6 +486,7 @@ uint64_t ResolveFunction(void* raw_context, uint64_t target_address) {
if (cvars::enable_host_guest_stack_synchronization) {
auto processor = thread_state->processor();
auto module_for_address =
processor->LookupModule(static_cast<uint32_t>(target_address));
@@ -498,6 +499,7 @@ uint64_t ResolveFunction(void* raw_context, uint64_t target_address) {
if (flags->is_return_site) {
auto ones_with_address = processor->FindFunctionsWithAddress(
static_cast<uint32_t>(target_address));
if (ones_with_address.size() != 0) {
// this loop to find a host address for the guest address is
// necessary because FindFunctionsWithAddress works via a range
@@ -618,21 +620,42 @@ uint64_t ResolveFunction(void* raw_context, uint64_t target_address) {
and 5 bytes for the jmp with no cycles taken for the jump
which will be predicted not taken.
Our handling for the check is implemented in X64HelperEmitter::EmitGuestAndHostSynchronizeStackHelper. we don't call it directly though,
instead we go through backend()->synchronize_guest_and_host_stack_helper_for_size(num_bytes_needed_to_represent_stack_size). we place the stack size after the
call instruction so we can load it in the helper and readjust the return address to point after the literal value.
Our handling for the check is implemented in
X64HelperEmitter::EmitGuestAndHostSynchronizeStackHelper. we
don't call it directly though, instead we go through
backend()->synchronize_guest_and_host_stack_helper_for_size(num_bytes_needed_to_represent_stack_size).
we place the stack size after the call instruction so we can
load it in the helper and readjust the return address to point
after the literal value.
The helper is going to search the array of stackpoints to find the first one that is greater than or equal to the current stack pointer, when it finds
the entry it will set the currently host rsp to the host stack pointer value in the entry, and then subtract the stack size of the caller from that.
the current stackpoint index is adjusted to point to the one after the stackpoint we restored to.
The helper is going to search the array of
stackpoints to find the first one that is greater than or
equal to the current stack pointer, when it finds the entry it
will set the currently host rsp to the host stack pointer
value in the entry, and then subtract the stack size of the
caller from that. the current stackpoint index is adjusted to
point to the one after the stackpoint we restored to.
The helper then jumps back to the function that was longjmp'ed to, with the host stack in its proper state. it just works!
The helper then jumps back to the function
that was longjmp'ed to, with the host stack in its proper
state. it just works!
*/
if (num_frames_bigger > 1) {
/*
* can't do anything about this right now :(
* epic mickey is quite slow due to having to call resolve on
* every longjmp, and it longjmps a lot but if we add an
* indirection we lose our stack misalignment check
*/
/* reinterpret_cast<X64CodeCache*>(backend->code_cache())
->AddIndirection(static_cast<uint32_t>(target_address),
static_cast<uint32_t>(host_address));
*/
return host_address;
}
}
@@ -1649,6 +1672,9 @@ Xbyak::Address X64Emitter::GetBackendFlagsPtr() const {
}
void X64Emitter::HandleStackpointOverflowError(ppc::PPCContext* context) {
if (debugging::IsDebuggerAttached()) {
debugging::Break();
}
// context->lr
// todo: show lr in message?
xe::FatalError(
@@ -1674,6 +1700,9 @@ void X64Emitter::PushStackpoint() {
mov(qword[rbx + offsetof(X64BackendStackpoint, host_stack_)], rsp);
mov(dword[rbx + offsetof(X64BackendStackpoint, guest_stack_)], r8d);
mov(r8d, qword[GetContextReg() + offsetof(ppc::PPCContext, lr)]);
mov(dword[rbx + offsetof(X64BackendStackpoint, guest_return_address_)], r8d);
if (IsFeatureEnabled(kX64FlagsIndependentVars)) {
inc(eax);
} else {
@@ -1716,24 +1745,6 @@ void X64Emitter::EnsureSynchronizedGuestAndHostStack() {
// need to be made
// that result in the stack not being 8 byte misaligned on context reentry
#if 0
Xbyak::Label skip{};
mov(r8, qword[GetContextReg() + offsetof(ppc::PPCContext, r[1])]);
mov(rbx, GetBackendCtxPtr(offsetof(X64BackendContext, stackpoints)));
imul(eax,
GetBackendCtxPtr(offsetof(X64BackendContext, current_stackpoint_depth)),
sizeof(X64BackendStackpoint));
sub(eax, sizeof(X64BackendStackpoint));
add(rbx, rax);
cmp(r8d, dword[rbx + offsetof(X64BackendStackpoint, guest_stack_)]);
jle(skip, T_NEAR);
Xbyak::Label skip{};
mov(r11d, stack_size());
call(backend_->synchronize_guest_and_host_stack_helper());
L(skip);
#endif
Xbyak::Label& return_from_sync = this->NewCachedLabel();
// if we got here somehow from setjmp or the like we ought to have a
@@ -1747,7 +1758,6 @@ void X64Emitter::EnsureSynchronizedGuestAndHostStack() {
uint32_t stack32 = static_cast<uint32_t>(e.stack_size());
auto backend = e.backend();
if (stack32 < 256) {
e.call(backend->synchronize_guest_and_host_stack_helper_for_size(1));
e.db(stack32);