From 1268b2dbc51f7370b836b4e7aa79076544015c7e Mon Sep 17 00:00:00 2001 From: thorpej Date: Fri, 18 Oct 2002 16:23:47 +0000 Subject: [PATCH] Add an x86_initialize_trampoline() function, similar to GCC 3.3, change INITIALIZE_TRAMPOLINE() to use it, and apply the following patch to it (which I have already submitted to GCC 3.3): * config/i386/i386.c (x86_initialize_trampoline): Emit a call to __enable_execute_stack with the address of the trampoline if TRANSFER_FROM_TRAMPOLINE is defined. Define a TRANSFER_FROM_TRAMPOLINE suitable for NetBSD targets, to enable stack execution on target machines which can separate exec permissions for a region: * config/netbsd.h (NETBSD_ENABLE_EXECUTE_STACK): Define. * config/alpha/netbsd.h (TRANSFER_FROM_TRAMPOLINE): Define as NETBSD_ENABLE_EXECUTE_STACK. * config/i386/netbsd-elf.h (TRANSFER_FROM_TRAMPOLINE): Ditto. * config/i386/netbsd.h (TRANSFER_FROM_TRAMPOLINE): Ditto. * config/sparc/netbsd-elf-common.h (TRANSFER_FROM_TRAMPOLINE): Ditto. * config/sparc/netbsd.h (TRANSFER_FROM_TRAMPOLINE): Ditto. (A similar patch will be submitted to GCC 3.3.) --- gnu/dist/toolchain/gcc/config/alpha/netbsd.h | 6 +++ gnu/dist/toolchain/gcc/config/i386/i386.c | 23 +++++++++ gnu/dist/toolchain/gcc/config/i386/i386.h | 14 ++---- .../toolchain/gcc/config/i386/netbsd-elf.h | 3 ++ gnu/dist/toolchain/gcc/config/i386/netbsd.h | 3 ++ gnu/dist/toolchain/gcc/config/netbsd.h | 48 +++++++++++++++++++ .../gcc/config/sparc/netbsd-elf-common.h | 3 ++ gnu/dist/toolchain/gcc/config/sparc/netbsd.h | 3 ++ 8 files changed, 92 insertions(+), 11 deletions(-) diff --git a/gnu/dist/toolchain/gcc/config/alpha/netbsd.h b/gnu/dist/toolchain/gcc/config/alpha/netbsd.h index 7e3ecc45a37b..612715362480 100644 --- a/gnu/dist/toolchain/gcc/config/alpha/netbsd.h +++ b/gnu/dist/toolchain/gcc/config/alpha/netbsd.h @@ -104,6 +104,12 @@ Boston, MA 02111-1307, USA. */ /* Show that we need a GP when profiling. */ #define TARGET_PROFILING_NEEDS_GP + +/* Attempt to enable execute permissions on the stack. */ + +#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK + + #define bsd4_4 #undef HAS_INIT_SECTION diff --git a/gnu/dist/toolchain/gcc/config/i386/i386.c b/gnu/dist/toolchain/gcc/config/i386/i386.c index 681d3064adcf..a9883aab4e87 100644 --- a/gnu/dist/toolchain/gcc/config/i386/i386.c +++ b/gnu/dist/toolchain/gcc/config/i386/i386.c @@ -5734,3 +5734,26 @@ memory_address_info (addr, disp_length) return len; } + +/* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. + CXT is an RTX for the static chain value for the function. */ +void +x86_initialize_trampoline (tramp, fnaddr, cxt) + rtx tramp, fnaddr, cxt; +{ + /* Compute offset from the end of the jmp to the target function. */ + rtx disp = expand_binop (SImode, sub_optab, fnaddr, + plus_constant (tramp, 10), + NULL_RTX, 1, OPTAB_DIRECT); + emit_move_insn (gen_rtx_MEM (QImode, tramp), GEN_INT (0xb9)); + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 1)), cxt); + emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 5)), + GEN_INT (0xe9)); + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 6)), disp); + +#ifdef TRANSFER_FROM_TRAMPOLINE + emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"), + 0, VOIDmode, 1, tramp, Pmode); +#endif +} diff --git a/gnu/dist/toolchain/gcc/config/i386/i386.h b/gnu/dist/toolchain/gcc/config/i386/i386.h index 0645052551ad..232e36bbfd23 100644 --- a/gnu/dist/toolchain/gcc/config/i386/i386.h +++ b/gnu/dist/toolchain/gcc/config/i386/i386.h @@ -1581,17 +1581,8 @@ do { \ FNADDR is an RTX for the address of the function's pure code. CXT is an RTX for the static chain value for the function. */ -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - /* Compute offset from the end of the jmp to the target function. */ \ - rtx disp = expand_binop (SImode, sub_optab, FNADDR, \ - plus_constant (TRAMP, 10), \ - NULL_RTX, 1, OPTAB_DIRECT); \ - emit_move_insn (gen_rtx_MEM (QImode, TRAMP), GEN_INT (0xb9)); \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 1)), CXT); \ - emit_move_insn (gen_rtx_MEM (QImode, plus_constant (TRAMP, 5)), GEN_INT (0xe9));\ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 6)), disp); \ -} +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ + x86_initialize_trampoline ((TRAMP), (FNADDR), (CXT)) /* Definitions for register eliminations. @@ -2766,6 +2757,7 @@ extern int ix86_can_use_return_insn_p (); extern int small_shift_operand (); extern char *output_ashl (); extern int memory_address_info (); +extern void x86_initialize_trampoline (); #ifdef NOTYET extern struct rtx_def *copy_all_rtx (); diff --git a/gnu/dist/toolchain/gcc/config/i386/netbsd-elf.h b/gnu/dist/toolchain/gcc/config/i386/netbsd-elf.h index e10edc347db1..66274094f43e 100644 --- a/gnu/dist/toolchain/gcc/config/i386/netbsd-elf.h +++ b/gnu/dist/toolchain/gcc/config/i386/netbsd-elf.h @@ -631,6 +631,9 @@ do { \ /* Default to pcc-struct-return, because this is the ELF abi and we don't care about compatibility with older gcc versions. */ #define DEFAULT_PCC_STRUCT_RETURN 1 + +/* Attempt to enable execute permissions on the stack. */ +#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK /* Profiling routines, partially copied from i386/osfrose.h. */ diff --git a/gnu/dist/toolchain/gcc/config/i386/netbsd.h b/gnu/dist/toolchain/gcc/config/i386/netbsd.h index d43acb652951..9544e8b3d54b 100644 --- a/gnu/dist/toolchain/gcc/config/i386/netbsd.h +++ b/gnu/dist/toolchain/gcc/config/i386/netbsd.h @@ -57,6 +57,9 @@ /* Don't default to pcc-struct-return, because gcc is the only compiler, and we want to retain compatibility with older gcc versions. */ #define DEFAULT_PCC_STRUCT_RETURN 0 + +/* Attempt to enable execute permissions on the stack. */ +#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK /* i386 netbsd still uses old binutils that don't insert nops by default when the .align directive demands to insert extra space in the text diff --git a/gnu/dist/toolchain/gcc/config/netbsd.h b/gnu/dist/toolchain/gcc/config/netbsd.h index 24988cbf7bf3..93a26faa6a39 100644 --- a/gnu/dist/toolchain/gcc/config/netbsd.h +++ b/gnu/dist/toolchain/gcc/config/netbsd.h @@ -282,3 +282,51 @@ do { \ %{static:-static}}" #endif /* NETBSD_ELF */ + + +/* Attempt to turn on execute permission for the stack. This may be + used by TRANSFER_FROM_TRAMPOLINE of the target needs it (that is, + if the target machine can change execute permissions on a page). + + There is no way to query the execute permission of the stack, so + we always issue the mprotect() call. + + Note that we go out of our way to use namespace-non-invasive calls + here. Unfortunately, there is no libc-internal name for mprotect(). + + Also note that no errors should be emitted by this code; it is considered + dangerous for library calls to send messages to stdout/stderr. */ + +#define NETBSD_ENABLE_EXECUTE_STACK \ +extern void __enable_execute_stack (void *); \ +void \ +__enable_execute_stack (addr) \ + void *addr; \ +{ \ + extern int mprotect (void *, size_t, int); \ + extern int __sysctl (int *, unsigned int, void *, size_t *, \ + void *, size_t); \ + \ + static int size; \ + static long mask; \ + \ + char *page, *end; \ + \ + if (size == 0) \ + { \ + int mib[2]; \ + size_t len; \ + \ + mib[0] = 6; /* CTL_HW */ \ + mib[1] = 7; /* HW_PAGESIZE */ \ + len = sizeof (size); \ + (void) __sysctl (mib, 2, &size, &len, NULL, 0); \ + mask = ~((long) size - 1); \ + } \ + \ + page = (char *) (((long) addr) & mask); \ + end = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \ + \ + /* 7 == PROT_READ | PROT_WRITE | PROT_EXEC */ \ + (void) mprotect (page, end - page, 7); \ +} diff --git a/gnu/dist/toolchain/gcc/config/sparc/netbsd-elf-common.h b/gnu/dist/toolchain/gcc/config/sparc/netbsd-elf-common.h index 89af4182e617..d4034f88b428 100644 --- a/gnu/dist/toolchain/gcc/config/sparc/netbsd-elf-common.h +++ b/gnu/dist/toolchain/gcc/config/sparc/netbsd-elf-common.h @@ -64,6 +64,9 @@ #undef STDC_0_IN_SYSTEM_HEADERS +/* Attempt to enable execute permissions on the stack. */ +#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK + /* XXX Redefine this; mucks with it. */ #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (%s)", TARGET_NAME); diff --git a/gnu/dist/toolchain/gcc/config/sparc/netbsd.h b/gnu/dist/toolchain/gcc/config/sparc/netbsd.h index d186835bb87c..45e406276a32 100644 --- a/gnu/dist/toolchain/gcc/config/sparc/netbsd.h +++ b/gnu/dist/toolchain/gcc/config/sparc/netbsd.h @@ -46,3 +46,6 @@ /* Name the default cpu target */ #define TARGET_CPU_DEFAULT TARGET_CPU_sparc + +/* Attempt to enable execute permissions on the stack. */ +#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK