Hi Christophe,

On 13/07/18 17:11, christophe.l...@st.com wrote:
From: Christophe Lyon <christophe.l...@linaro.org>

In FDPIC mode, the trampoline generated to support pointers to nested
functions looks like:

           .word trampoline address
           .word trampoline GOT address
           ldr            r12, [pc, #8]
           ldr            r9, [pc, #8]
           ldr           pc, [pc]

The comment in the code says the last one is:
ldr           pc,  [pc, #8] ; #4 for Thumb2

I'm assuming the code one is correct.

           .word static chain value
           .word GOT address
           .word function's address

because in FDPIC function pointers are actually pointers to function
descriptors, we have to actually generate a function descriptor for
the trampoline.

2018-XX-XX  Christophe Lyon  <christophe.l...@st.com>
        Mickaël Guêné <mickael.gu...@st.com>

        gcc/
        * config/arm/arm.c (arm_asm_trampoline_template): Add FDPIC
        support.
        (arm_trampoline_init): Likewise.
        (arm_trampoline_init): Likewise.
        * config/arm/arm.h (TRAMPOLINE_SIZE): Likewise.

Change-Id: I4b5127261a9aefa0f0318f110574ec07a856aeb1

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 51da2bc..ffc9128 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -3950,13 +3950,50 @@ arm_warn_func_return (tree decl)
            .word static chain value
            .word function's address
    XXX FIXME: When the trampoline returns, r8 will be clobbered.  */
+/* In FDPIC mode, the trampoline looks like:
+          .word trampoline address
+          .word trampoline GOT address
+          ldr            r12, [pc, #8] ; #4 for Thumb2
+          ldr            r9,  [pc, #8] ; #4 for Thumb2
+          ldr           pc,  [pc, #8] ; #4 for Thumb2
+          .word static chain value
+          .word GOT address
+          .word function's address
+*/
 static void
 arm_asm_trampoline_template (FILE *f)
 {
   fprintf (f, "\t.syntax unified\n");

-  if (TARGET_ARM)
+  if (TARGET_FDPIC)
+    {
+      /* The first two words are a function descriptor pointing to the
+        trampoline code just below.  */
+      if (TARGET_ARM)
+       fprintf (f, "\t.arm\n");
+      else if (TARGET_THUMB2)
+       fprintf (f, "\t.thumb\n");
+      else
+       /* Only ARM and Thumb-2 are supported.  */
+       gcc_assert ( !TARGET_ARM && !TARGET_THUMB2);
+

This cannot trigger based on the two clauses above. I think you want to just 
make it gcc_unreachable ().

+      assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+      assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+      /* Trampoline code which sets the static chain register but also
+        PIC register before jumping into real code.  */
+      asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+                  STATIC_CHAIN_REGNUM, PC_REGNUM,
+                  TARGET_THUMB2 ? 8 : 4);
+      asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+                  PIC_OFFSET_TABLE_REGNUM, PC_REGNUM,
+                  TARGET_THUMB2 ? 8 : 4);
+      asm_fprintf (f, "\tldr\t%r, [%r, #%d]\n",
+                  PC_REGNUM, PC_REGNUM,
+                  TARGET_THUMB2 ? 8 : 4);
+      assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+    }
+  else if (TARGET_ARM)
     {
       fprintf (f, "\t.arm\n");
       asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", STATIC_CHAIN_REGNUM, PC_REGNUM);
@@ -3997,12 +4034,37 @@ arm_trampoline_init (rtx m_tramp, tree fndecl, rtx 
chain_value)
   emit_block_move (m_tramp, assemble_trampoline_template (),
                    GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);

-  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
-  emit_move_insn (mem, chain_value);
+  if (TARGET_FDPIC)
+    {
+      rtx funcdesc = XEXP (DECL_RTL (fndecl), 0);
+      rtx fnaddr = gen_rtx_MEM (Pmode, funcdesc);
+      rtx gotaddr = gen_rtx_MEM (Pmode, plus_constant (Pmode, funcdesc, 4));
+      rtx trampoline_code_start
+       = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 : 8);

9? Can you comment on this value?

+
+      /* Write initial funcdesc which points to the trampoline.  */
+      mem = adjust_address (m_tramp, SImode, 0);
+      emit_move_insn (mem, trampoline_code_start);
+      mem = adjust_address (m_tramp, SImode, 4);
+      emit_move_insn (mem, gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM));
+      /* Setup static chain.  */
+      mem = adjust_address (m_tramp, SImode, 20);
+      emit_move_insn (mem, chain_value);
+      /* GOT + real function entry point.  */
+      mem = adjust_address (m_tramp, SImode, 24);
+      emit_move_insn (mem, gotaddr);
+      mem = adjust_address (m_tramp, SImode, 28);
+      emit_move_insn (mem, fnaddr);
+    }
+  else
+    {
+      mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
+      emit_move_insn (mem, chain_value);

-  mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 12 : 16);
-  fnaddr = XEXP (DECL_RTL (fndecl), 0);
-  emit_move_insn (mem, fnaddr);
+      mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 12 : 16);
+      fnaddr = XEXP (DECL_RTL (fndecl), 0);
+      emit_move_insn (mem, fnaddr);
+    }

   a_tramp = XEXP (m_tramp, 0);
   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
@@ -4016,7 +4078,9 @@ arm_trampoline_init (rtx m_tramp, tree fndecl, rtx 
chain_value)
 static rtx
 arm_trampoline_adjust_address (rtx addr)
 {
-  if (TARGET_THUMB)
+  /* For FDPIC don't fix trampoline address since it's a function
+     descriptor and not a function address.  */
+  if (TARGET_THUMB && !TARGET_FDPIC)
     addr = expand_simple_binop (Pmode, IOR, addr, const1_rtx,
                                 NULL, 0, OPTAB_LIB_WIDEN);
   return addr;
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 4671d64..22a65a1 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1581,7 +1581,7 @@ typedef struct
 #define INIT_EXPANDERS  arm_init_expanders ()

 /* Length in units of the trampoline for entering a nested function.  */
-#define TRAMPOLINE_SIZE  (TARGET_32BIT ? 16 : 20)
+#define TRAMPOLINE_SIZE  (TARGET_FDPIC ? 32 : (TARGET_32BIT ? 16 : 20))

 /* Alignment required for a trampoline in bits.  */
 #define TRAMPOLINE_ALIGNMENT  32
--
2.6.3


Reply via email to