i386.md (vswapmov): New.
2009-10-12 Stefan Dösinger <stefan@codeweavers.com> * config/i386/i386.md (vswapmov): New. * config/i386/i386.c (ix86_handle_fndecl_attribute): New. (ix86_function_ms_hook_prologue): New. (ix86_expand_prologue): Handle ms_hook_prologue attribute. * configure.ac: Test for swap suffix support in as. * configure: Rebuild. From-SVN: r152670
This commit is contained in:
parent
ea1b2f550d
commit
afd2c302c6
7 changed files with 158 additions and 1 deletions
|
@ -1,3 +1,12 @@
|
|||
2009-10-12 Stefan Dösinger <stefan@codeweavers.com>
|
||||
|
||||
* config/i386/i386.md (vswapmov): New.
|
||||
* config/i386/i386.c (ix86_handle_fndecl_attribute): New.
|
||||
(ix86_function_ms_hook_prologue): New.
|
||||
(ix86_expand_prologue): Handle ms_hook_prologue attribute.
|
||||
* configure.ac: Test for swap suffix support in as.
|
||||
* configure: Rebuild.
|
||||
|
||||
2009-10-12 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/41680
|
||||
|
|
|
@ -4774,6 +4774,25 @@ ix86_function_type_abi (const_tree fntype)
|
|||
return ix86_abi;
|
||||
}
|
||||
|
||||
static bool
|
||||
ix86_function_ms_hook_prologue (const_tree fntype)
|
||||
{
|
||||
if (!TARGET_64BIT)
|
||||
{
|
||||
if (lookup_attribute ("ms_hook_prologue", DECL_ATTRIBUTES (fntype)))
|
||||
{
|
||||
if (decl_function_context (fntype) != NULL_TREE)
|
||||
{
|
||||
error_at (DECL_SOURCE_LOCATION (fntype),
|
||||
"ms_hook_prologue is not compatible with nested function");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum calling_abi
|
||||
ix86_function_abi (const_tree fndecl)
|
||||
{
|
||||
|
@ -8295,6 +8314,7 @@ ix86_expand_prologue (void)
|
|||
bool pic_reg_used;
|
||||
struct ix86_frame frame;
|
||||
HOST_WIDE_INT allocate;
|
||||
int gen_frame_pointer = frame_pointer_needed;
|
||||
|
||||
ix86_finalize_stack_realign_flags ();
|
||||
|
||||
|
@ -8307,6 +8327,46 @@ ix86_expand_prologue (void)
|
|||
|
||||
ix86_compute_frame_layout (&frame);
|
||||
|
||||
if (ix86_function_ms_hook_prologue (current_function_decl))
|
||||
{
|
||||
rtx push, mov;
|
||||
|
||||
/* Make sure the function starts with
|
||||
8b ff movl.s %edi,%edi
|
||||
55 push %ebp
|
||||
8b ec movl.s %esp,%ebp
|
||||
|
||||
This matches the hookable function prologue in Win32 API functions in Microsoft Windows
|
||||
XP Service Pack 2 and newer. Wine uses this to enable Windows apps to hook the Win32 API
|
||||
functions provided by Wine */
|
||||
insn = emit_insn (gen_vswapmov (gen_rtx_REG (SImode, DI_REG), gen_rtx_REG (SImode, DI_REG)));
|
||||
push = emit_insn (gen_push (hard_frame_pointer_rtx));
|
||||
mov = emit_insn (gen_vswapmov (hard_frame_pointer_rtx, stack_pointer_rtx));
|
||||
|
||||
if (frame_pointer_needed && !(crtl->drap_reg && crtl->stack_realign_needed))
|
||||
{
|
||||
/* The push %ebp and movl.s %esp, %ebp already set up the frame pointer. No need to do
|
||||
this again. */
|
||||
gen_frame_pointer = 0;
|
||||
RTX_FRAME_RELATED_P (push) = 1;
|
||||
RTX_FRAME_RELATED_P (mov) = 1;
|
||||
if (ix86_cfa_state->reg == stack_pointer_rtx)
|
||||
{
|
||||
ix86_cfa_state->reg = hard_frame_pointer_rtx;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the frame pointer is not needed, pop %ebp again. This could be optimized for cases where
|
||||
ebp needs to be backed up for some other reason.
|
||||
|
||||
If stack realignment is needed, pop the base pointer again, align the stack, and later
|
||||
regenerate the frame pointer setup. The frame pointer generated by the hook prologue
|
||||
is not aligned, so it can't be used */
|
||||
insn = emit_insn ((*ix86_gen_pop1) (hard_frame_pointer_rtx));
|
||||
}
|
||||
}
|
||||
|
||||
/* The first insn of a function that accepts its static chain on the
|
||||
stack is to push the register that would be filled in by a direct
|
||||
call. This insn will be skipped by the trampoline. */
|
||||
|
@ -8378,7 +8438,7 @@ ix86_expand_prologue (void)
|
|||
/* Note: AT&T enter does NOT have reversed args. Enter is probably
|
||||
slower on all targets. Also sdb doesn't like it. */
|
||||
|
||||
if (frame_pointer_needed)
|
||||
if (gen_frame_pointer)
|
||||
{
|
||||
insn = emit_insn (gen_push (hard_frame_pointer_rtx));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
|
@ -26470,6 +26530,35 @@ ix86_handle_struct_attribute (tree *node, tree name,
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
static tree
|
||||
ix86_handle_fndecl_attribute (tree *node, tree name,
|
||||
tree args ATTRIBUTE_UNUSED,
|
||||
int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
|
||||
{
|
||||
if (TREE_CODE (*node) != FUNCTION_DECL)
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute only applies to functions",
|
||||
name);
|
||||
*no_add_attrs = true;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if (TARGET_64BIT)
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute only available for 32-bit",
|
||||
name);
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
#ifndef HAVE_AS_IX86_SWAP
|
||||
sorry ("ms_hook_prologue attribute needs assembler swap suffix support");
|
||||
#endif
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
static bool
|
||||
ix86_ms_bitfield_layout_p (const_tree record_type)
|
||||
{
|
||||
|
@ -29512,6 +29601,7 @@ static const struct attribute_spec ix86_attribute_table[] =
|
|||
/* ms_abi and sysv_abi calling convention function attributes. */
|
||||
{ "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute },
|
||||
{ "sysv_abi", 0, 0, false, true, true, ix86_handle_abi_attribute },
|
||||
{ "ms_hook_prologue", 0, 0, true, false, false, ix86_handle_fndecl_attribute },
|
||||
/* End element. */
|
||||
{ NULL, 0, 0, false, false, false, NULL }
|
||||
};
|
||||
|
|
|
@ -241,6 +241,7 @@
|
|||
(UNSPECV_RDTSC 18)
|
||||
(UNSPECV_RDTSCP 19)
|
||||
(UNSPECV_RDPMC 20)
|
||||
(UNSPECV_VSWAPMOV 21)
|
||||
])
|
||||
|
||||
;; Constants to represent pcomtrue/pcomfalse variants
|
||||
|
@ -14893,6 +14894,16 @@
|
|||
(set_attr "length_immediate" "0")
|
||||
(set_attr "modrm" "0")])
|
||||
|
||||
(define_insn "vswapmov"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(match_operand:SI 1 "register_operand" "r"))
|
||||
(unspec_volatile [(const_int 0)] UNSPECV_VSWAPMOV)]
|
||||
""
|
||||
"movl.s\t{%1, %0|%0, %1}"
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "length_immediate" "0")
|
||||
(set_attr "modrm" "0")])
|
||||
|
||||
;; Pad to 16-byte boundary, max skip in op0. Used to avoid
|
||||
;; branch prediction penalty for the third jump in a 16-byte
|
||||
;; block on K8.
|
||||
|
|
|
@ -3047,6 +3047,12 @@ foo: nop
|
|||
[AC_DEFINE(HAVE_AS_IX86_SAHF, 1,
|
||||
[Define if your assembler supports the sahf mnemonic.])])
|
||||
|
||||
gcc_GAS_CHECK_FEATURE([swap suffix],
|
||||
gcc_cv_as_ix86_swap,,,
|
||||
[movl.s %esp, %ebp],,
|
||||
[AC_DEFINE(HAVE_AS_IX86_SWAP, 1,
|
||||
[Define if your assembler supports the swap suffix.])])
|
||||
|
||||
gcc_GAS_CHECK_FEATURE([different section symbol subtraction],
|
||||
gcc_cv_as_ix86_diff_sect_delta,,,
|
||||
[.section .rodata
|
||||
|
|
|
@ -2679,6 +2679,14 @@ when targeting Windows. On all other systems, the default is the AMD ABI.
|
|||
|
||||
Note, This feature is currently sorried out for Windows targets trying to
|
||||
|
||||
@item ms_hook_prologue
|
||||
@cindex @code{ms_hook_prologue} attribute
|
||||
|
||||
On 32 bit i[34567]86-*-* targets, you can use this function attribute to make
|
||||
gcc generate the "hot-patching" function prologue used in Win32 API
|
||||
functions in Microsoft Windows XP Service Pack 2 and newer. This requires
|
||||
support for the swap suffix in the assembler. (GNU Binutils 2.19.51 or later)
|
||||
|
||||
@item naked
|
||||
@cindex function without a prologue/epilogue code
|
||||
Use this attribute on the ARM, AVR, IP2K and SPU ports to indicate that
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2009-10-12 Stefan Dösinger <stefan@codeweavers.com>
|
||||
|
||||
* gcc.target/i386/ms_hook_prologue.c: New testcase.
|
||||
|
||||
2009-10-12 Michael Matz <matz@suse.de>
|
||||
|
||||
* gcc.dg/plugin/one_time_plugin.c: Update test to use the cfg
|
||||
|
|
29
gcc/testsuite/gcc.target/i386/ms_hook_prologue.c
Normal file
29
gcc/testsuite/gcc.target/i386/ms_hook_prologue.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* Test that the ms_hook_prologue attribute generates the correct code. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-require-effective-target ilp32 } */
|
||||
/* { dg-options "-O2 -fomit-frame-pointer" } */
|
||||
|
||||
int __attribute__ ((__ms_hook_prologue__)) foo ()
|
||||
{
|
||||
unsigned char *ptr = (unsigned char *) foo;
|
||||
|
||||
/* The NOP mov must not be optimized away by optimizations.
|
||||
The push %ebp, mov %esp, %ebp must not be removed by
|
||||
-fomit-frame-pointer */
|
||||
|
||||
/* movl.s %edi, %edi */
|
||||
if(*ptr++ != 0x8b) return 1;
|
||||
if(*ptr++ != 0xff) return 1;
|
||||
/* push %ebp */
|
||||
if(*ptr++ != 0x55) return 1;
|
||||
/* movl.s %esp, %ebp */
|
||||
if(*ptr++ != 0x8b) return 1;
|
||||
if(*ptr++ != 0xec) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
return foo();
|
||||
}
|
Loading…
Add table
Reference in a new issue