aboutsummaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/config.host1
-rw-r--r--libgcc/config/i386/heap-trampoline.c40
2 files changed, 38 insertions, 3 deletions
diff --git a/libgcc/config.host b/libgcc/config.host
index 3e7d00f..59a42d3 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -774,6 +774,7 @@ i[34567]86-*-linux*)
tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules"
tm_file="${tm_file} i386/elf-lib.h"
md_unwind_header=i386/linux-unwind.h
+ tmake_file="${tmake_file} i386/t-heap-trampoline"
;;
i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-kopensolaris*-gnu)
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
diff --git a/libgcc/config/i386/heap-trampoline.c b/libgcc/config/i386/heap-trampoline.c
index 657b344..1df0aa0 100644
--- a/libgcc/config/i386/heap-trampoline.c
+++ b/libgcc/config/i386/heap-trampoline.c
@@ -29,12 +29,13 @@ void *allocate_trampoline_page (void);
void __gcc_nested_func_ptr_created (void *chain, void *func, void *dst);
void __gcc_nested_func_ptr_deleted (void);
+#if __x86_64__
static const uint8_t trampoline_insns[] = {
- /* movabs $<chain>,%r11 */
+ /* movabs $<func>,%r11 */
0x49, 0xbb,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* movabs $<func>,%r10 */
+ /* movabs $<chain>,%r10 */
0x49, 0xba,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -54,6 +55,33 @@ union ix86_trampoline {
} fields;
};
+#elif __i386__
+
+static const uint8_t trampoline_insns[] = {
+ /* movl $<chain>,%ecx */
+ 0xb9,
+ 0x00, 0x00, 0x00, 0x00,
+
+ /* jmpl <func>-. */
+ 0xe9,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+union ix86_trampoline {
+ uint8_t insns[sizeof(trampoline_insns)];
+
+ struct __attribute__((packed)) fields {
+ uint8_t insn_0[1];
+ void *chain_ptr;
+ uint8_t insn_1[1];
+ uintptr_t func_offset;
+ } fields;
+};
+
+#else
+#error unsupported architecture/ABI
+#endif
+
struct tramp_ctrl_data
{
struct tramp_ctrl_data *prev;
@@ -145,8 +173,14 @@ __gcc_nested_func_ptr_created (void *chain, void *func, void *dst)
memcpy (trampoline->insns, trampoline_insns,
sizeof(trampoline_insns));
- trampoline->fields.func_ptr = func;
trampoline->fields.chain_ptr = chain;
+#if __x86_64__
+ trampoline->fields.func_ptr = func;
+#elif __i386__
+ uintptr_t off_add = (uintptr_t) &trampoline->fields.func_offset;
+ off_add += 4;
+ trampoline->fields.func_offset = (uintptr_t)func - off_add;
+#endif
#if __APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101400
/* Re-enable write protection. */