summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Dösinger <stefan@codeweavers.com>2009-10-12 16:36:37 +0000
committerRichard Henderson <rth@gcc.gnu.org>2009-10-12 09:36:37 -0700
commitafd2c302c6f4377ed46d809744115e67d363d997 (patch)
tree458ae7e284b9bdd2f115c05aee9e40fdb0d47167
parentea1b2f550d560f911ee70052713b7e5a17d44f33 (diff)
downloadgcc-afd2c302c6f4377ed46d809744115e67d363d997.tar.gz
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
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/i386/i386.c92
-rw-r--r--gcc/config/i386/i386.md11
-rw-r--r--gcc/configure.ac6
-rw-r--r--gcc/doc/extend.texi8
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/i386/ms_hook_prologue.c29
7 files changed, 158 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b79f323a11e..0714158ea99 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index b5bb6a0352f..73913b8376d 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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 }
};
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 22ea39cf79b..3fa938ea3bb 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -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.
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 7947d285629..dd3b7e890d2 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -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
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 6f0955577c3..da886a30f11 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0c0360679e6..07c5ef5c442 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.target/i386/ms_hook_prologue.c b/gcc/testsuite/gcc.target/i386/ms_hook_prologue.c
new file mode 100644
index 00000000000..19438e7583f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ms_hook_prologue.c
@@ -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();
+}