[x64] Fix up unwind info for emitted functions.

- [x64] Track size of code within emitted functions (prolog, body, epilog).
- [x64] Don't use hardcoded prolog size in generated unwind info.
- [x64] Update URLs to MSDN documentation on UNWIND_INFO/UNWIND_CODE.
This commit is contained in:
gibbed
2019-08-23 05:34:19 -05:00
committed by Rick Gibbed
parent 918a7d4365
commit 0dc4a13db3
6 changed files with 166 additions and 54 deletions

View File

@@ -407,13 +407,25 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
// rdx = arg0 (context)
// r8 = arg1 (guest return address)
struct _code_offsets {
size_t prolog;
size_t body;
size_t epilog;
size_t tail;
} code_offsets = {};
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
code_offsets.prolog = getSize();
// rsp + 0 = return address
mov(qword[rsp + 8 * 3], r8);
mov(qword[rsp + 8 * 2], rdx);
mov(qword[rsp + 8 * 1], rcx);
sub(rsp, stack_size);
code_offsets.body = getSize();
// Save nonvolatile registers.
EmitSaveNonvolatileRegs();
@@ -424,13 +436,26 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
EmitLoadNonvolatileRegs();
code_offsets.epilog = getSize();
add(rsp, stack_size);
mov(rcx, qword[rsp + 8 * 1]);
mov(rdx, qword[rsp + 8 * 2]);
mov(r8, qword[rsp + 8 * 3]);
ret();
void* fn = Emplace(stack_size);
code_offsets.tail = getSize();
assert_zero(code_offsets.prolog);
EmitFunctionInfo func_info = {};
func_info.code_size.total = getSize();
func_info.code_size.prolog = code_offsets.body - code_offsets.prolog;
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.stack_size = stack_size;
void* fn = Emplace(func_info);
return (HostToGuestThunk)fn;
}
@@ -440,10 +465,22 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
// r8 = arg1
// r9 = arg2
struct _code_offsets {
size_t prolog;
size_t body;
size_t epilog;
size_t tail;
} code_offsets = {};
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
code_offsets.prolog = getSize();
// rsp + 0 = return address
sub(rsp, stack_size);
code_offsets.body = getSize();
// Save off volatile registers.
EmitSaveVolatileRegs();
@@ -453,10 +490,23 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
EmitLoadVolatileRegs();
code_offsets.epilog = getSize();
add(rsp, stack_size);
ret();
void* fn = Emplace(stack_size);
code_offsets.tail = getSize();
assert_zero(code_offsets.prolog);
EmitFunctionInfo func_info = {};
func_info.code_size.total = getSize();
func_info.code_size.prolog = code_offsets.body - code_offsets.prolog;
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.stack_size = stack_size;
void* fn = Emplace(func_info);
return (GuestToHostThunk)fn;
}
@@ -466,11 +516,23 @@ extern "C" uint64_t ResolveFunction(void* raw_context, uint32_t target_address);
ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
// ebx = target PPC address
// rcx = context
struct _code_offsets {
size_t prolog;
size_t body;
size_t epilog;
size_t tail;
} code_offsets = {};
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
code_offsets.prolog = getSize();
// rsp + 0 = return address
sub(rsp, stack_size);
code_offsets.body = getSize();
// Save volatile registers
EmitSaveVolatileRegs();
@@ -481,10 +543,23 @@ ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
EmitLoadVolatileRegs();
code_offsets.epilog = getSize();
add(rsp, stack_size);
jmp(rax);
void* fn = Emplace(stack_size);
code_offsets.tail = getSize();
assert_zero(code_offsets.prolog);
EmitFunctionInfo func_info = {};
func_info.code_size.total = getSize();
func_info.code_size.prolog = code_offsets.body - code_offsets.prolog;
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.stack_size = stack_size;
void* fn = Emplace(func_info);
return (ResolveFunctionThunk)fn;
}