Hi Christophe,

I'll be honest, I'm not very familiar with this part of the compiler.
I'll let Ramana or Richard comment on the approach.
A description of what this patch does and how would be appreciated.

Some comments inline nevertheless :)

Thanks,
Kyrill
On 25/05/18 09:03, Christophe Lyon wrote:
2018-XX-XX  Christophe Lyon <christophe.l...@st.com>
        Mickaël Guêné <mickael.gu...@st.com>

        libgcc/
        * unwind-arm-common.inc (ARM_SET_R7_RT_SIGRETURN)
        (THUMB2_SET_R7_RT_SIGRETURN, FDPIC_LDR_R12_WITH_FUNCDESC)
        (FDPIC_LDR_R9_WITH_GOT, FDPIC_LDR_PC_WITH_RESTORER)
        (FDPIC_FUNCDESC_OFFSET, ARM_NEW_RT_SIGFRAME_UCONTEXT)
        (ARM_UCONTEXT_SIGCONTEXT, ARM_SIGCONTEXT_R0): New.
        (__gnu_personality_sigframe_fdpic): New.
        (get_eit_entry): Add FDPIC signal frame support.

Change-Id: I7f9527cc50665dd1a731b7badf71c319fb38bf57

diff --git a/libgcc/unwind-arm-common.inc b/libgcc/unwind-arm-common.inc
index f5415c1..80d1e88 100644
--- a/libgcc/unwind-arm-common.inc
+++ b/libgcc/unwind-arm-common.inc
@@ -30,6 +30,21 @@
 #include <sys/sdt.h>
 #endif

+#if __FDPIC__
+/* Load r7 with rt_sigreturn value.  */
+#define ARM_SET_R7_RT_SIGRETURN                0xe3a070ad
+#define THUMB2_SET_R7_RT_SIGRETURN     0x07adf04f
+/* FDPIC jump to restorer sequence.  */
+#define FDPIC_LDR_R12_WITH_FUNCDESC    0xe59fc004
+#define FDPIC_LDR_R9_WITH_GOT          0xe59c9004
+#define FDPIC_LDR_PC_WITH_RESTORER     0xe59cf000
+#define FDPIC_FUNCDESC_OFFSET          12
+/* Signal frame offsets.  */
+#define ARM_NEW_RT_SIGFRAME_UCONTEXT   0x80
+#define ARM_UCONTEXT_SIGCONTEXT                0x14
+#define ARM_SIGCONTEXT_R0              0xc
+#endif

I think these are instruction opcodes? If so, please include their expected 
disassembly
in a comment next to them. That way we stand a chance of validating whether 
they actually
do what we want them to do.

+
 /* We add a prototype for abort here to avoid creating a dependency on
    target headers.  */
 extern void abort (void);
@@ -195,6 +210,46 @@ search_EIT_table (const __EIT_entry * table, int nrec, _uw 
return_address)
     }
 }

+#if __FDPIC__
+/* FIXME: partial support (VFP not restored) but should be sufficient
+   to allow unwinding.  */

Not a fan of these FIXMEs in patch submissions.
Is the patch incomplete?
Does the missing support not matter?
If VFP is not supported properly then we should be rejecting
building such configurations for the time being.

+static _Unwind_Reason_Code
+__gnu_personality_sigframe_fdpic (_Unwind_State state,
+                       _Unwind_Control_Block *ucbp,
+                       _Unwind_Context *context)
+{
+    unsigned int sp;
+    unsigned int pc;
+    unsigned int funcdesc;
+    unsigned int handler;
+    unsigned int first_handler_instruction;
+    int i;
+
+    _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &sp);
+    _Unwind_VRS_Get (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &pc);
+
+    funcdesc = *(unsigned int *)(pc + FDPIC_FUNCDESC_OFFSET);
+    handler = *(unsigned int *)(funcdesc);
+    first_handler_instruction = *(unsigned int *)(handler & ~1);
+
+    /* Adjust SP to point to the start of registers according to
+       signal type.  */
+    if (first_handler_instruction == ARM_SET_R7_RT_SIGRETURN
+       || first_handler_instruction == THUMB2_SET_R7_RT_SIGRETURN)
+       sp += ARM_NEW_RT_SIGFRAME_UCONTEXT
+         + ARM_UCONTEXT_SIGCONTEXT
+         + ARM_SIGCONTEXT_R0;
+    else
+       sp += ARM_UCONTEXT_SIGCONTEXT
+         + ARM_SIGCONTEXT_R0;
+    /* Restore regs saved on stack by the kernel.  */
+    for (i = 0; i < 16; i++)
+       _Unwind_VRS_Set (context, _UVRSC_CORE, i, _UVRSD_UINT32, sp + 4 * i);
+
+    return _URC_CONTINUE_UNWIND;
+}
+#endif
+
 /* Find the exception index table eintry for the given address.
    Fill in the relevant fields of the UCB.
    Returns _URC_FAILURE if an error occurred, _URC_OK on success.  */
@@ -218,6 +273,24 @@ get_eit_entry (_Unwind_Control_Block *ucbp, _uw 
return_address)
&nrec);
       if (!eitp)
         {
+#if __FDPIC__
+         /* If we are unwinding a signal handler then perhaps we have
+            reached a trampoline.  Try to detect jump to restorer
+            sequence.  */
+         _uw *pc = (_uw *)((return_address+2) & ~3);
+         if (pc[0] == FDPIC_LDR_R12_WITH_FUNCDESC
+             && pc[1] == FDPIC_LDR_R9_WITH_GOT
+             && pc[2] == FDPIC_LDR_PC_WITH_RESTORER)
+           {

As I said, I'll let Richard or Ramana comment on the approach but I don't see 
any
other code in this file doing such instruction matching...

+             struct funcdesc_t *funcdesc = (struct funcdesc_t *)
+               &__gnu_personality_sigframe_fdpic;
+
+             UCB_PR_ADDR (ucbp) = funcdesc->ptr;
+             UCB_PR_GOT (ucbp) = funcdesc->got;
+
+             return _URC_OK;
+           }
+#endif
           UCB_PR_ADDR (ucbp) = 0;
           return _URC_FAILURE;
         }
@@ -232,6 +305,24 @@ get_eit_entry (_Unwind_Control_Block *ucbp, _uw 
return_address)

   if (!eitp)
     {
+#if __FDPIC__
+      /* If we are unwinding a signal handler then perhaps we have
+        reached a trampoline.  Try to detect jump to restorer
+        sequence.  */
+      _uw *pc = (_uw *)((return_address+2) & ~3);
+      if (pc[0] == FDPIC_LDR_R12_WITH_FUNCDESC
+         && pc[1] == FDPIC_LDR_R9_WITH_GOT
+         && pc[2] == FDPIC_LDR_PC_WITH_RESTORER)
+       {
+         struct funcdesc_t *funcdesc = (struct funcdesc_t *)
+           &__gnu_personality_sigframe_fdpic;
+
+         UCB_PR_ADDR (ucbp) = funcdesc->ptr;
+         UCB_PR_GOT (ucbp) = funcdesc->got;
+
+         return _URC_OK;
+       }
+#endif
       UCB_PR_ADDR (ucbp) = 0;
       return _URC_FAILURE;
     }
@@ -240,6 +331,24 @@ get_eit_entry (_Unwind_Control_Block *ucbp, _uw 
return_address)
   /* Can this frame be unwound at all?  */
   if (eitp->content == EXIDX_CANTUNWIND)
     {
+#if __FDPIC__
+      /* If we are unwinding a signal handler then perhaps we have
+        reached a trampoline.  Try to detect jump to restorer
+        sequence.  */
+      _uw *pc = (_uw *)((return_address+2) & ~3);
+      if (pc[0] == FDPIC_LDR_R12_WITH_FUNCDESC
+         && pc[1] == FDPIC_LDR_R9_WITH_GOT
+         && pc[2] == FDPIC_LDR_PC_WITH_RESTORER)
+       {
+         struct funcdesc_t *funcdesc = (struct funcdesc_t *)
+           &__gnu_personality_sigframe_fdpic;
+
+         UCB_PR_ADDR (ucbp) = funcdesc->ptr;
+         UCB_PR_GOT (ucbp) = funcdesc->got;
+
+         return _URC_OK;
+       }
+#endif
       UCB_PR_ADDR (ucbp) = 0;
       return _URC_END_OF_STACK;
     }
--
2.6.3


Reply via email to