Commit b663a6de authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Add support for jump instructions in function epilogs.

parent 34c875bf
...@@ -2586,7 +2586,7 @@ static int get_opcode_size( struct opcode op ) ...@@ -2586,7 +2586,7 @@ static int get_opcode_size( struct opcode op )
} }
} }
static BOOL is_inside_epilog( BYTE *pc ) static BOOL is_inside_epilog( BYTE *pc, ULONG64 base, const RUNTIME_FUNCTION *function )
{ {
/* add or lea must be the first instruction, and it must have a rex.W prefix */ /* add or lea must be the first instruction, and it must have a rex.W prefix */
if ((pc[0] & 0xf8) == 0x48) if ((pc[0] & 0xf8) == 0x48)
...@@ -2629,9 +2629,9 @@ static BOOL is_inside_epilog( BYTE *pc ) ...@@ -2629,9 +2629,9 @@ static BOOL is_inside_epilog( BYTE *pc )
for (;;) for (;;)
{ {
BYTE rex = 0; DWORD offset;
if ((*pc & 0xf0) == 0x40) rex = *pc++ & 0x0f; /* rex prefix */ if ((*pc & 0xf0) == 0x40) pc++; /* rex prefix */
switch (*pc) switch (*pc)
{ {
...@@ -2648,9 +2648,14 @@ static BOOL is_inside_epilog( BYTE *pc ) ...@@ -2648,9 +2648,14 @@ static BOOL is_inside_epilog( BYTE *pc )
case 0xc2: /* ret $nn */ case 0xc2: /* ret $nn */
case 0xc3: /* ret */ case 0xc3: /* ret */
return TRUE; return TRUE;
case 0xe9: /* jmp nnnn */
offset = pc + 5 + *(LONG *)(pc + 1) - (BYTE *)base;
return (offset >= function->BeginAddress && offset < function->EndAddress);
case 0xeb: /* jmp n */
offset = pc + 2 + (signed char)pc[1] - (BYTE *)base;
return (offset >= function->BeginAddress && offset < function->EndAddress);
case 0xf3: /* rep; ret (for amd64 prediction bug) */ case 0xf3: /* rep; ret (for amd64 prediction bug) */
return pc[1] == 0xc3; return pc[1] == 0xc3;
/* FIXME: add various jump instructions */
} }
return FALSE; return FALSE;
} }
...@@ -2708,7 +2713,12 @@ static void interpret_epilog( BYTE *pc, CONTEXT *context, KNONVOLATILE_CONTEXT_P ...@@ -2708,7 +2713,12 @@ static void interpret_epilog( BYTE *pc, CONTEXT *context, KNONVOLATILE_CONTEXT_P
context->Rip = *(ULONG64 *)context->Rsp; context->Rip = *(ULONG64 *)context->Rsp;
context->Rsp += sizeof(ULONG64); context->Rsp += sizeof(ULONG64);
return; return;
/* FIXME: add various jump instructions */ case 0xe9: /* jmp nnnn */
pc += 5 + *(LONG *)(pc + 1);
continue;
case 0xeb: /* jmp n */
pc += 2 + (signed char)pc[1];
continue;
} }
return; return;
} }
...@@ -2753,7 +2763,7 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc, ...@@ -2753,7 +2763,7 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
else else
{ {
prolog_offset = ~0; prolog_offset = ~0;
if (is_inside_epilog( (BYTE *)pc )) if (is_inside_epilog( (BYTE *)pc, base, function ))
{ {
interpret_epilog( (BYTE *)pc, context, ctx_ptr ); interpret_epilog( (BYTE *)pc, context, ctx_ptr );
*frame_ret = frame; *frame_ret = frame;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment