From 24321dbcd92569b17cf1094353b87552d5fe1807 Mon Sep 17 00:00:00 2001 From: gibbed Date: Fri, 23 Aug 2019 06:09:42 -0500 Subject: [PATCH] [x64] Fix up offset of stack alloc in prolog for unwind info. - [x64] Track offset of stack alloc in prolog within emitted functions. - [x64] Don't use hardcoded offset of stack alloc in prolog in generated unwind info. --- src/xenia/cpu/backend/x64/x64_backend.cc | 14 +++++++++++++- src/xenia/cpu/backend/x64/x64_code_cache.cc | 2 +- src/xenia/cpu/backend/x64/x64_code_cache.h | 3 ++- src/xenia/cpu/backend/x64/x64_code_cache_win.cc | 12 +++++++----- src/xenia/cpu/backend/x64/x64_emitter.cc | 8 +++++++- src/xenia/cpu/backend/x64/x64_emitter.h | 2 +- 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/xenia/cpu/backend/x64/x64_backend.cc b/src/xenia/cpu/backend/x64/x64_backend.cc index 708cd884b..8d3d48cee 100644 --- a/src/xenia/cpu/backend/x64/x64_backend.cc +++ b/src/xenia/cpu/backend/x64/x64_backend.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2019 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -409,6 +409,7 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() { struct _code_offsets { size_t prolog; + size_t prolog_stack_alloc; size_t body; size_t epilog; size_t tail; @@ -424,6 +425,7 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() { mov(qword[rsp + 8 * 1], rcx); sub(rsp, stack_size); + code_offsets.prolog_stack_alloc = getSize(); code_offsets.body = getSize(); // Save nonvolatile registers. @@ -453,6 +455,8 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() { func_info.code_size.body = code_offsets.epilog - code_offsets.body; func_info.code_size.epilog = code_offsets.tail - code_offsets.epilog; func_info.code_size.tail = getSize() - code_offsets.tail; + func_info.prolog_stack_alloc_offset = + code_offsets.prolog_stack_alloc - code_offsets.prolog; func_info.stack_size = stack_size; void* fn = Emplace(func_info); @@ -467,6 +471,7 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() { struct _code_offsets { size_t prolog; + size_t prolog_stack_alloc; size_t body; size_t epilog; size_t tail; @@ -479,6 +484,7 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() { // rsp + 0 = return address sub(rsp, stack_size); + code_offsets.prolog_stack_alloc = getSize(); code_offsets.body = getSize(); // Save off volatile registers. @@ -504,6 +510,8 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() { func_info.code_size.body = code_offsets.epilog - code_offsets.body; func_info.code_size.epilog = code_offsets.tail - code_offsets.epilog; func_info.code_size.tail = getSize() - code_offsets.tail; + func_info.prolog_stack_alloc_offset = + code_offsets.prolog_stack_alloc - code_offsets.prolog; func_info.stack_size = stack_size; void* fn = Emplace(func_info); @@ -519,6 +527,7 @@ ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() { struct _code_offsets { size_t prolog; + size_t prolog_stack_alloc; size_t body; size_t epilog; size_t tail; @@ -531,6 +540,7 @@ ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() { // rsp + 0 = return address sub(rsp, stack_size); + code_offsets.prolog_stack_alloc = getSize(); code_offsets.body = getSize(); // Save volatile registers @@ -557,6 +567,8 @@ ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() { func_info.code_size.body = code_offsets.epilog - code_offsets.body; func_info.code_size.epilog = code_offsets.tail - code_offsets.epilog; func_info.code_size.tail = getSize() - code_offsets.tail; + func_info.prolog_stack_alloc_offset = + code_offsets.prolog_stack_alloc - code_offsets.prolog; func_info.stack_size = stack_size; void* fn = Emplace(func_info); diff --git a/src/xenia/cpu/backend/x64/x64_code_cache.cc b/src/xenia/cpu/backend/x64/x64_code_cache.cc index 85adb6579..fe0fd55a1 100644 --- a/src/xenia/cpu/backend/x64/x64_code_cache.cc +++ b/src/xenia/cpu/backend/x64/x64_code_cache.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2019 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ diff --git a/src/xenia/cpu/backend/x64/x64_code_cache.h b/src/xenia/cpu/backend/x64/x64_code_cache.h index 5dc2b580e..dbe59dcde 100644 --- a/src/xenia/cpu/backend/x64/x64_code_cache.h +++ b/src/xenia/cpu/backend/x64/x64_code_cache.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2019 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -33,6 +33,7 @@ struct EmitFunctionInfo { size_t tail; size_t total; } code_size; + size_t prolog_stack_alloc_offset; // offset of instruction after stack alloc size_t stack_size; }; diff --git a/src/xenia/cpu/backend/x64/x64_code_cache_win.cc b/src/xenia/cpu/backend/x64/x64_code_cache_win.cc index 9cd910d6a..66c16d9cf 100644 --- a/src/xenia/cpu/backend/x64/x64_code_cache_win.cc +++ b/src/xenia/cpu/backend/x64/x64_code_cache_win.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2019 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -248,6 +248,10 @@ void Win32X64CodeCache::InitializeUnwindEntry( assert_true(func_info.code_size.prolog < 256); // needs to fit into a uint8_t auto prolog_size = static_cast(func_info.code_size.prolog); + assert_true(func_info.prolog_stack_alloc_offset < + 256); // needs to fit into a uint8_t + auto prolog_stack_alloc_offset = + static_cast(func_info.prolog_stack_alloc_offset); if (!func_info.stack_size) { // https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64#struct-unwind_info @@ -268,8 +272,7 @@ void Win32X64CodeCache::InitializeUnwindEntry( // https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64#struct-unwind_code unwind_code = &unwind_info->UnwindCode[unwind_info->CountOfCodes++]; - unwind_code->CodeOffset = - 14; // end of instruction + 1 == offset of next instruction + unwind_code->CodeOffset = prolog_stack_alloc_offset; unwind_code->UnwindOp = UWOP_ALLOC_SMALL; unwind_code->OpInfo = func_info.stack_size / 8 - 1; } else { @@ -285,8 +288,7 @@ void Win32X64CodeCache::InitializeUnwindEntry( // https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64#struct-unwind_code unwind_code = &unwind_info->UnwindCode[unwind_info->CountOfCodes++]; - unwind_code->CodeOffset = - 7; // end of instruction + 1 == offset of next instruction + unwind_code->CodeOffset = prolog_stack_alloc_offset; unwind_code->UnwindOp = UWOP_ALLOC_LARGE; unwind_code->OpInfo = 0; // One slot for size diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc index 52d4ff020..216efd9bc 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.cc +++ b/src/xenia/cpu/backend/x64/x64_emitter.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2019 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -163,6 +163,7 @@ bool X64Emitter::Emit(HIRBuilder* builder, EmitFunctionInfo& func_info) { struct _code_offsets { size_t prolog; + size_t prolog_stack_alloc; size_t body; size_t epilog; size_t tail; @@ -183,6 +184,9 @@ bool X64Emitter::Emit(HIRBuilder* builder, EmitFunctionInfo& func_info) { stack_size_ = stack_size; sub(rsp, (uint32_t)stack_size); + + code_offsets.prolog_stack_alloc = getSize(); + mov(qword[rsp + StackLayout::GUEST_CTX_HOME], GetContextReg()); mov(qword[rsp + StackLayout::GUEST_RET_ADDR], rcx); mov(qword[rsp + StackLayout::GUEST_CALL_RET_ADDR], 0); @@ -275,6 +279,8 @@ bool X64Emitter::Emit(HIRBuilder* builder, EmitFunctionInfo& func_info) { func_info.code_size.body = code_offsets.epilog - code_offsets.body; func_info.code_size.epilog = code_offsets.tail - code_offsets.epilog; func_info.code_size.tail = getSize() - code_offsets.tail; + func_info.prolog_stack_alloc_offset = + code_offsets.prolog_stack_alloc - code_offsets.prolog; return true; } diff --git a/src/xenia/cpu/backend/x64/x64_emitter.h b/src/xenia/cpu/backend/x64/x64_emitter.h index 626894aaa..af38fb739 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.h +++ b/src/xenia/cpu/backend/x64/x64_emitter.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * + * Copyright 2019 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */