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