Message ID | 20190515124006.25840-10-christophe.lyon@st.com |
---|---|
State | Superseded |
Headers | show |
Series | FDPIC ABI for ARM | expand |
Hi Christophe On 5/15/19 1:39 PM, Christophe Lyon wrote: > 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, #8] > .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. > > 2019-XX-XX Christophe Lyon <christophe.lyon@st.com> > Mickaël Guêné <mickael.guene@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: Idc4d5f629ae4f8d79bdf9623517481d524a0c144 > > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c > index 40e3f3b..99d13bf 100644 > --- a/gcc/config/arm/arm.c > +++ b/gcc/config/arm/arm.c > @@ -3976,13 +3976,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 > +*/ I think this comment is not right for Thumb2. These load instructionshave 32-bit encodings, even in Thumb2 (they use high registers). Also, please merge this comment with the one above (no separate /**/) > > 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_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); As above, I think the offset should be 8 for both Arm and Thumb2. Thanks, Kyrill > + 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); > @@ -4023,12 +4060,40 @@ 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)); > + /* The function start address is at offset 8, but in Thumb mode > + we want bit 0 set to 1 to indicate Thumb-ness, hence 9 > + below. */ > + rtx trampoline_code_start > + = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 : 8); > + > + /* 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"), > @@ -4042,7 +4107,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 45c0e2b..f80df63 100644 > --- a/gcc/config/arm/arm.h > +++ b/gcc/config/arm/arm.h > @@ -1602,7 +1602,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 >
On 7/16/19 12:18 PM, Kyrill Tkachov wrote: > Hi Christophe > > On 5/15/19 1:39 PM, Christophe Lyon wrote: > > 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, #8] > > .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. > > > > 2019-XX-XX Christophe Lyon <christophe.lyon@st.com> > > Mickaël Guêné <mickael.guene@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: Idc4d5f629ae4f8d79bdf9623517481d524a0c144 > > > > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c > > index 40e3f3b..99d13bf 100644 > > --- a/gcc/config/arm/arm.c > > +++ b/gcc/config/arm/arm.c > > @@ -3976,13 +3976,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 > > +*/ > > > I think this comment is not right for Thumb2. > > These load instructionshave 32-bit encodings, even in Thumb2 (they use > high registers). Andre and Wilco pointed out to me offline that the offset should be #4 for Arm mode. The Arm ARM at E1.2.3 says: PC, the program counter * When executing an A32 instruction, PC reads as the address of the current instruction plus 8. * When executing a T32 instruction, PC reads as the address of the current instruction plus 4. Thanks, Kyrill > > Also, please merge this comment with the one above (no separate /**/) > > > > > 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_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); > > > As above, I think the offset should be 8 for both Arm and Thumb2. > > Thanks, > > Kyrill > > > > + 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); > > @@ -4023,12 +4060,40 @@ 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)); > > + /* The function start address is at offset 8, but in Thumb mode > > + we want bit 0 set to 1 to indicate Thumb-ness, hence 9 > > + below. */ > > + rtx trampoline_code_start > > + = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 > : 8); > > + > > + /* 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"), > > @@ -4042,7 +4107,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 45c0e2b..f80df63 100644 > > --- a/gcc/config/arm/arm.h > > +++ b/gcc/config/arm/arm.h > > @@ -1602,7 +1602,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 > >
On Tue, 16 Jul 2019 at 14:42, Kyrill Tkachov <kyrylo.tkachov@foss.arm.com> wrote: > > > On 7/16/19 12:18 PM, Kyrill Tkachov wrote: > > Hi Christophe > > > > On 5/15/19 1:39 PM, Christophe Lyon wrote: > > > 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, #8] > > > .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. > > > > > > 2019-XX-XX Christophe Lyon <christophe.lyon@st.com> > > > Mickaël Guêné <mickael.guene@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: Idc4d5f629ae4f8d79bdf9623517481d524a0c144 > > > > > > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c > > > index 40e3f3b..99d13bf 100644 > > > --- a/gcc/config/arm/arm.c > > > +++ b/gcc/config/arm/arm.c > > > @@ -3976,13 +3976,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 > > > +*/ > > > > > > I think this comment is not right for Thumb2. > > > > These load instructionshave 32-bit encodings, even in Thumb2 (they use > > high registers). > > Andre and Wilco pointed out to me offline that the offset should be #4 > for Arm mode. > > The Arm ARM at E1.2.3 says: > > PC, the program counter > > * When executing an A32 instruction, PC reads as the address of the > current instruction plus 8. > > * When executing a T32 instruction, PC reads as the address of the > current instruction plus 4. > Yes, it looks like the code is right, and the comment is wrong: - offset 8 for thumb2 mode - offset 4 for arm mode Thanks, Christophe > Thanks, > > Kyrill > > > > > > Also, please merge this comment with the one above (no separate /**/) > > > > > > > > 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_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); > > > > > > As above, I think the offset should be 8 for both Arm and Thumb2. > > > > Thanks, > > > > Kyrill > > > > > > > + 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); > > > @@ -4023,12 +4060,40 @@ 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)); > > > + /* The function start address is at offset 8, but in Thumb mode > > > + we want bit 0 set to 1 to indicate Thumb-ness, hence 9 > > > + below. */ > > > + rtx trampoline_code_start > > > + = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 > > : 8); > > > + > > > + /* 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"), > > > @@ -4042,7 +4107,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 45c0e2b..f80df63 100644 > > > --- a/gcc/config/arm/arm.h > > > +++ b/gcc/config/arm/arm.h > > > @@ -1602,7 +1602,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 > > >
On 31/07/2019 16:44, Christophe Lyon wrote: > On Tue, 16 Jul 2019 at 14:42, Kyrill Tkachov > <kyrylo.tkachov@foss.arm.com> wrote: >> >> >> On 7/16/19 12:18 PM, Kyrill Tkachov wrote: >>> Hi Christophe >>> >>> On 5/15/19 1:39 PM, Christophe Lyon wrote: >>>> 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, #8] >>>> .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. >>>> >>>> 2019-XX-XX Christophe Lyon <christophe.lyon@st.com> >>>> Mickaël Guêné <mickael.guene@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: Idc4d5f629ae4f8d79bdf9623517481d524a0c144 >>>> >>>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c >>>> index 40e3f3b..99d13bf 100644 >>>> --- a/gcc/config/arm/arm.c >>>> +++ b/gcc/config/arm/arm.c >>>> @@ -3976,13 +3976,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 >>>> +*/ >>> >>> >>> I think this comment is not right for Thumb2. >>> >>> These load instructionshave 32-bit encodings, even in Thumb2 (they use >>> high registers). >> >> Andre and Wilco pointed out to me offline that the offset should be #4 >> for Arm mode. >> >> The Arm ARM at E1.2.3 says: >> >> PC, the program counter >> >> * When executing an A32 instruction, PC reads as the address of the >> current instruction plus 8. >> >> * When executing a T32 instruction, PC reads as the address of the >> current instruction plus 4. >> > > Yes, it looks like the code is right, and the comment is wrong: > - offset 8 for thumb2 mode > - offset 4 for arm mode > Here is the updated version > Thanks, > > Christophe > >> Thanks, >> >> Kyrill >> >> >>> >>> Also, please merge this comment with the one above (no separate /**/) >>> >>>> >>>> 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_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); >>> >>> >>> As above, I think the offset should be 8 for both Arm and Thumb2. >>> >>> Thanks, >>> >>> Kyrill >>> >>> >>>> + 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); >>>> @@ -4023,12 +4060,40 @@ 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)); >>>> + /* The function start address is at offset 8, but in Thumb mode >>>> + we want bit 0 set to 1 to indicate Thumb-ness, hence 9 >>>> + below. */ >>>> + rtx trampoline_code_start >>>> + = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 >>> : 8); >>>> + >>>> + /* 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"), >>>> @@ -4042,7 +4107,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 45c0e2b..f80df63 100644 >>>> --- a/gcc/config/arm/arm.h >>>> +++ b/gcc/config/arm/arm.h >>>> @@ -1602,7 +1602,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 >>>> > . > From 6b116cbb0a84f467e1419385a271ecbc1963ffc1 Mon Sep 17 00:00:00 2001 From: Christophe Lyon <christophe.lyon@linaro.org> Date: Thu, 8 Feb 2018 14:34:20 +0100 Subject: [ARM/FDPIC v6 09/24] [ARM] FDPIC: Add support for taking address of nested function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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, #8] .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. 2019-XX-XX Christophe Lyon <christophe.lyon@st.com> Mickaël Guêné <mickael.guene@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: Idc4d5f629ae4f8d79bdf9623517481d524a0c144 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index bd09536..4827988 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -3974,14 +3974,52 @@ arm_warn_func_return (tree decl) ldr pc, [pc] .word static chain value .word function's address - XXX FIXME: When the trampoline returns, r8 will be clobbered. */ + 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 Arm mode + ldr r9, [pc, #8] ; #4 for Arm mode + ldr pc, [pc, #8] ; #4 for Arm mode + .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_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); @@ -4022,12 +4060,40 @@ 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)); + /* The function start address is at offset 8, but in Thumb mode + we want bit 0 set to 1 to indicate Thumb-ness, hence 9 + below. */ + rtx trampoline_code_start + = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 : 8); + + /* 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"), @@ -4041,7 +4107,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 45c0e2b..f80df63 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1602,7 +1602,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
On 8/29/19 4:36 PM, Christophe Lyon wrote: > On 31/07/2019 16:44, Christophe Lyon wrote: >> On Tue, 16 Jul 2019 at 14:42, Kyrill Tkachov >> <kyrylo.tkachov@foss.arm.com> wrote: >>> >>> >>> On 7/16/19 12:18 PM, Kyrill Tkachov wrote: >>>> Hi Christophe >>>> >>>> On 5/15/19 1:39 PM, Christophe Lyon wrote: >>>>> 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, #8] >>>>> .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. >>>>> >>>>> 2019-XX-XX Christophe Lyon <christophe.lyon@st.com> >>>>> Mickaël Guêné <mickael.guene@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: Idc4d5f629ae4f8d79bdf9623517481d524a0c144 >>>>> >>>>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c >>>>> index 40e3f3b..99d13bf 100644 >>>>> --- a/gcc/config/arm/arm.c >>>>> +++ b/gcc/config/arm/arm.c >>>>> @@ -3976,13 +3976,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 >>>>> +*/ >>>> >>>> >>>> I think this comment is not right for Thumb2. >>>> >>>> These load instructionshave 32-bit encodings, even in Thumb2 (they use >>>> high registers). >>> >>> Andre and Wilco pointed out to me offline that the offset should be #4 >>> for Arm mode. >>> >>> The Arm ARM at E1.2.3 says: >>> >>> PC, the program counter >>> >>> * When executing an A32 instruction, PC reads as the address of the >>> current instruction plus 8. >>> >>> * When executing a T32 instruction, PC reads as the address of the >>> current instruction plus 4. >>> >> >> Yes, it looks like the code is right, and the comment is wrong: >> - offset 8 for thumb2 mode >> - offset 4 for arm mode >> > Here is the updated version > Ok with a fixed ChangeLog (it currently mentions arm_trampoline_init twice but doesn't mention arm_trampoline_adjust_address) Thanks, Kyrill >> Thanks, >> >> Christophe >> >>> Thanks, >>> >>> Kyrill >>> >>> >>>> >>>> Also, please merge this comment with the one above (no separate /**/) >>>> >>>>> >>>>> 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_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); >>>> >>>> >>>> As above, I think the offset should be 8 for both Arm and Thumb2. >>>> >>>> Thanks, >>>> >>>> Kyrill >>>> >>>> >>>>> + 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); >>>>> @@ -4023,12 +4060,40 @@ 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)); >>>>> + /* The function start address is at offset 8, but in Thumb >>>>> mode >>>>> + we want bit 0 set to 1 to indicate Thumb-ness, hence 9 >>>>> + below. */ >>>>> + rtx trampoline_code_start >>>>> + = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 >>>> : 8); >>>>> + >>>>> + /* 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"), >>>>> @@ -4042,7 +4107,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 45c0e2b..f80df63 100644 >>>>> --- a/gcc/config/arm/arm.h >>>>> +++ b/gcc/config/arm/arm.h >>>>> @@ -1602,7 +1602,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 >>>>> >> . >> >
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 40e3f3b..99d13bf 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -3976,13 +3976,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_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); @@ -4023,12 +4060,40 @@ 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)); + /* The function start address is at offset 8, but in Thumb mode + we want bit 0 set to 1 to indicate Thumb-ness, hence 9 + below. */ + rtx trampoline_code_start + = plus_constant (Pmode, XEXP (m_tramp, 0), TARGET_THUMB2 ? 9 : 8); + + /* 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"), @@ -4042,7 +4107,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 45c0e2b..f80df63 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1602,7 +1602,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