From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 98757 invoked by alias); 30 Aug 2019 14:32:40 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 98741 invoked by uid 89); 30 Aug 2019 14:32:39 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-16.4 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 30 Aug 2019 14:32:37 +0000 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CD1AD3D96D; Fri, 30 Aug 2019 14:32:35 +0000 (UTC) Received: from localhost (unknown [10.33.36.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4315360BEC; Fri, 30 Aug 2019 14:32:35 +0000 (UTC) Date: Fri, 30 Aug 2019 14:44:00 -0000 From: Jonathan Wakely To: Kyrill Tkachov Cc: Christophe Lyon , "gcc-patches@gcc.gnu.org" , libstdc++@gcc.gnu.org, ian@airs.com Subject: Re: [ARM/FDPIC v5 06/21] [ARM] FDPIC: Add support for c++ exceptions Message-ID: <20190830143234.GN9487@redhat.com> References: <20190515124006.25840-1-christophe.lyon@st.com> <20190515124006.25840-7-christophe.lyon@st.com> <597c97c0-16a5-f886-3d1a-8e2f0b089259@foss.arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1; format=flowed Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <597c97c0-16a5-f886-3d1a-8e2f0b089259@foss.arm.com> X-Clacks-Overhead: GNU Terry Pratchett User-Agent: Mutt/1.12.0 (2019-05-25) X-SW-Source: 2019-08/txt/msg02084.txt.bz2 On 30/08/19 10:02 +0100, Kyrill Tkachov wrote: >As Richard mentioned in an earlier post the generic libgcc and >libstdc++ changes will need approval from the relevant maintainers. > >CC'ing the libstdc++ list and the libgcc maintainer. The libstdc++ change is OK for trunk. >On 5/15/19 1:39 PM, Christophe Lyon wrote: >>The main difference with existing support is that function addresses >>are function descriptor addresses instead. This means that all code >>dealing with function pointers now has to cope with function >>descriptors instead. >> >>For the same reason, Linux kernel helpers can no longer be called by >>dereferencing their address, so we implement wrappers that directly >>call the kernel helpers. >> >>When restoring a function address, we also have to restore the FDPIC >>register value (r9). >> >>2019-XX-XX  Christophe Lyon  >>        Mickaël Guêné >> >>        gcc/ >>        * ginclude/unwind-arm-common.h (unwinder_cache): Add reserved5 >>        field. >>        (FDPIC_REGNUM): New define. >> >>        libgcc/ >>        * config/arm/linux-atomic.c (__kernel_cmpxchg): Add FDPIC support. >>        (__kernel_dmb): Likewise. >>        (__fdpic_cmpxchg): New function. >>        (__fdpic_dmb): New function. >>        * config/arm/unwind-arm.h (FDPIC_REGNUM): New define. >>        (gnu_Unwind_Find_got): New function. >>        (_Unwind_decode_typeinfo_ptr): Add FDPIC support. >>        * unwind-arm-common.inc (UCB_PR_GOT): New. >>        (funcdesc_t): New struct. >>        (get_eit_entry): Add FDPIC support. >>        (unwind_phase2): Likewise. >>        (unwind_phase2_forced): Likewise. >>        (__gnu_Unwind_RaiseException): Likewise. >>        (__gnu_Unwind_Resume): Likewise. >>        (__gnu_Unwind_Backtrace): Likewise. >>        * unwind-pe.h (read_encoded_value_with_base): Likewise. >> >>        libstdc++/ >>        * libsupc++/eh_personality.cc (get_ttype_entry): Add FDPIC >>        support. >> >>Change-Id: I64b81cfaf390a05f2fd121f44ba1912cb4b47cae >> >>diff --git a/gcc/ginclude/unwind-arm-common.h >>b/gcc/ginclude/unwind-arm-common.h >>index 6df783e..d4eb03e 100644 >>--- a/gcc/ginclude/unwind-arm-common.h >>+++ b/gcc/ginclude/unwind-arm-common.h >>@@ -91,7 +91,7 @@ extern "C" { >>           _uw reserved2;  /* Personality routine address */ >>           _uw reserved3;  /* Saved callsite address */ >>           _uw reserved4;  /* Forced unwind stop arg */ >>-         _uw reserved5; >>+         _uw reserved5;  /* Personality routine GOT value in FDPIC >>mode.  */ >>         } >>       unwinder_cache; >>       /* Propagation barrier cache (valid after phase 1): */ >>diff --git a/libgcc/config/arm/linux-atomic.c >>b/libgcc/config/arm/linux-atomic.c >>index 06a6d46..565f829 100644 >>--- a/libgcc/config/arm/linux-atomic.c >>+++ b/libgcc/config/arm/linux-atomic.c >>@@ -25,11 +25,62 @@ see the files COPYING3 and COPYING.RUNTIME >>respectively.  If not, see >> >> /* Kernel helper for compare-and-exchange.  */ >> typedef int (__kernel_cmpxchg_t) (int oldval, int newval, int *ptr); >>-#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0) >>+ >>+#define STR(X) #X >>+#define XSTR(X) STR(X) >>+ >>+#define KERNEL_CMPXCHG 0xffff0fc0 >>+ >>+#if __FDPIC__ >>+/* Non-FDPIC ABIs call __kernel_cmpxchg directly by dereferencing its >>+   address, but under FDPIC we would generate a broken call >>+   sequence. That's why we have to implement __kernel_cmpxchg and >>+   __kernel_dmb here: this way, the FDPIC call sequence works.  */ >>+#define __kernel_cmpxchg __fdpic_cmpxchg >>+#else >>+#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) KERNEL_CMPXCHG) >>+#endif >> >> /* Kernel helper for memory barrier.  */ >> typedef void (__kernel_dmb_t) (void); >>-#define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) >>+ >>+#define KERNEL_DMB 0xffff0fa0 >>+ >>+#if __FDPIC__ >>+#define __kernel_dmb __fdpic_dmb >>+#else >>+#define __kernel_dmb (*(__kernel_dmb_t *) KERNEL_DMB) >>+#endif >>+ >>+#if __FDPIC__ >>+static int __fdpic_cmpxchg (int oldval, int newval, int *ptr) >>+{ >>+  int result; >>+ >>+  asm volatile ( >>+               "ldr    ip, 1f\n\t" >>+               "bx     ip\n\t" >>+               "1:\n\t" >>+               ".word " XSTR(KERNEL_CMPXCHG) "\n\t" >>+               : "=r" (result) >>+               : "r" (oldval) , "r" (newval), "r" (ptr) >>+               : "r3", "memory"); >>+  /* The result is actually returned by the kernel helper, we need >>+     this to avoid a warning.  */ >>+  return result; >>+} >>+ >>+static void __fdpic_dmb (void) >>+{ >>+  asm volatile ( >>+               "ldr    ip, 1f\n\t" >>+               "bx     ip\n\t" >>+               "1:\n\t" >>+               ".word " XSTR(KERNEL_DMB) "\n\t" >>+               ); >>+} >>+ >>+#endif >> >> /* Note: we implement byte, short and int versions of atomic >>operations using >>    the above kernel helpers; see linux-atomic-64bit.c for "long >>long" (64-bit) >>diff --git a/libgcc/config/arm/unwind-arm.h >>b/libgcc/config/arm/unwind-arm.h >>index 43c5379..2bf320a 100644 >>--- a/libgcc/config/arm/unwind-arm.h >>+++ b/libgcc/config/arm/unwind-arm.h >>@@ -33,9 +33,33 @@ >> /* Use IP as a scratch register within the personality routine.  */ >> #define UNWIND_POINTER_REG 12 >> >>+#define FDPIC_REGNUM 9 >>+ >>+#define STR(x) #x >>+#define XSTR(x) STR(x) >>+ >> #ifdef __cplusplus >> extern "C" { >> #endif >>+_Unwind_Ptr __attribute__((weak)) __gnu_Unwind_Find_got (_Unwind_Ptr); >>+ >>+static inline _Unwind_Ptr gnu_Unwind_Find_got (_Unwind_Ptr ptr) >>+{ >>+    _Unwind_Ptr res; >>+ >>+    if (__gnu_Unwind_Find_got) >>+       res =  __gnu_Unwind_Find_got (ptr); >>+    else >>+      { >>+       asm volatile ("mov %[result], r" XSTR(FDPIC_REGNUM) >>+                     : [result]"=r" (res) >>+                     : >>+                     :); >>+      } >>+ >>+    return res; >>+} >>+ >>   /* Decode an R_ARM_TARGET2 relocation.  */ >>   static inline _Unwind_Word >>   _Unwind_decode_typeinfo_ptr (_Unwind_Word base __attribute__ >>((unused)), >>@@ -48,7 +72,12 @@ extern "C" { >>       if (!tmp) >>         return 0; >> >>-#if (defined(linux) && !defined(__uClinux__)) || defined(__NetBSD__) \ >>+#if __FDPIC__ >>+      /* For FDPIC, we store the offset of the GOT entry. */ >>+      /* So, first get GOT from dynamic linker and then use >>indirect access.  */ >>+      tmp += gnu_Unwind_Find_got (ptr); >>+      tmp = *(_Unwind_Word *) tmp; >>+#elif (defined(linux) && !defined(__uClinux__)) || defined(__NetBSD__) \ >>     || defined(__FreeBSD__) || defined(__fuchsia__) >>       /* Pc-relative indirect.  */ >> #define _GLIBCXX_OVERRIDE_TTYPE_ENCODING (DW_EH_PE_pcrel | >>DW_EH_PE_indirect) >>diff --git a/libgcc/unwind-arm-common.inc b/libgcc/unwind-arm-common.inc >>index fd572fe..0bacc11 100644 >>--- a/libgcc/unwind-arm-common.inc >>+++ b/libgcc/unwind-arm-common.inc >>@@ -62,6 +62,7 @@ __gnu_Unwind_Find_exidx (_Unwind_Ptr, int *); >> #define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2) >> #define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3) >> #define UCB_FORCED_STOP_ARG(ucbp) ((ucbp)->unwinder_cache.reserved4) >>+#define UCB_PR_GOT(ucbp) ((ucbp)->unwinder_cache.reserved5) >> >> /* Unwind descriptors.  */ >> >>@@ -85,6 +86,16 @@ typedef struct __EIT_entry >>   _uw content; >> } __EIT_entry; >> >>+#ifdef __FDPIC__ >>+ >>+/* Only used in FDPIC case.  */ >>+struct funcdesc_t >>+{ >>+  unsigned int ptr; >>+  unsigned int got; >>+}; >>+#endif >>+ >> /* Assembly helper functions.  */ >> >> /* Restore core register state.  Never returns.  */ >>@@ -259,7 +270,21 @@ get_eit_entry (_Unwind_Control_Block *ucbp, _uw >>return_address) >>     { >>       /* One of the predefined standard routines.  */ >>       _uw idx = (*(_uw *) ucbp->pr_cache.ehtp >> 24) & 0xf; >>+#if __FDPIC__ >>+      { >>+       struct funcdesc_t *funcdesc >>+         = (struct funcdesc_t *) __gnu_unwind_get_pr_addr (idx); >>+       if (funcdesc) >>+         { >>+           UCB_PR_ADDR (ucbp) = funcdesc->ptr; >>+           UCB_PR_GOT (ucbp) = funcdesc->got; >>+         } >>+       else >>+         UCB_PR_ADDR (ucbp) = 0; >>+      } >>+#else >>       UCB_PR_ADDR (ucbp) = __gnu_unwind_get_pr_addr (idx); >>+#endif >>       if (UCB_PR_ADDR (ucbp) == 0) >>         { >>           /* Failed */ >>@@ -270,6 +295,10 @@ get_eit_entry (_Unwind_Control_Block *ucbp, _uw >>return_address) >>     { >>       /* Execute region offset to PR */ >>       UCB_PR_ADDR (ucbp) = selfrel_offset31 (ucbp->pr_cache.ehtp); >>+#if __FDPIC__ >>+      UCB_PR_GOT (ucbp) >>+       = (unsigned int) gnu_Unwind_Find_got ((_Unwind_Ptr) >>UCB_PR_ADDR (ucbp)); >>+#endif >>     } >>   return _URC_OK; >> } >>@@ -291,14 +320,29 @@ unwind_phase2 (_Unwind_Control_Block * ucbp, >>phase2_vrs * vrs) >>       UCB_SAVED_CALLSITE_ADDR (ucbp) = VRS_PC(vrs); >> >>       /* Call the pr to decide what to do.  */ >>+#if __FDPIC__ >>+      { >>+       volatile struct funcdesc_t funcdesc; >>+       funcdesc.ptr = UCB_PR_ADDR (ucbp); >>+       funcdesc.got = UCB_PR_GOT (ucbp); >>+       pr_result = ((personality_routine) &funcdesc) >>+         (_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs); >>+      } >>+#else >>       pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) >>         (_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs); >>+#endif >>     } >>   while (pr_result == _URC_CONTINUE_UNWIND); >> >>   if (pr_result != _URC_INSTALL_CONTEXT) >>     abort(); >> >>+#if __FDPIC__ >>+  /* r9 could have been lost due to PLT jump.  Restore correct value.  */ >>+  vrs->core.r[FDPIC_REGNUM] = gnu_Unwind_Find_got (VRS_PC (vrs)); >>+#endif >>+ >>   uw_restore_core_regs (vrs, &vrs->core); >> } >> >>@@ -346,8 +390,18 @@ unwind_phase2_forced (_Unwind_Control_Block >>*ucbp, phase2_vrs *entry_vrs, >>           next_vrs = saved_vrs; >> >>           /* Call the pr to decide what to do.  */ >>+#if __FDPIC__ >>+         { >>+           volatile struct funcdesc_t funcdesc; >>+           funcdesc.ptr = UCB_PR_ADDR (ucbp); >>+           funcdesc.got = UCB_PR_GOT (ucbp); >>+           pr_result = ((personality_routine) &funcdesc) >>+             (action, ucbp, (void *) &next_vrs); >>+         } >>+#else >>           pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) >>             (action, ucbp, (void *) &next_vrs); >>+#endif >> >>           saved_vrs.prev_sp = VRS_SP (&next_vrs); >>         } >>@@ -384,6 +438,11 @@ unwind_phase2_forced (_Unwind_Control_Block >>*ucbp, phase2_vrs *entry_vrs, >>       return _URC_FAILURE; >>     } >> >>+#if __FDPIC__ >>+  /* r9 could have been lost due to PLT jump.  Restore correct value.  */ >>+  saved_vrs.core.r[FDPIC_REGNUM] = gnu_Unwind_Find_got (VRS_PC >>(&saved_vrs)); >>+#endif >>+ >>   uw_restore_core_regs (&saved_vrs, &saved_vrs.core); >> } >> >>@@ -429,8 +488,18 @@ __gnu_Unwind_RaiseException >>(_Unwind_Control_Block * ucbp, >>         return _URC_FAILURE; >> >>       /* Call the pr to decide what to do.  */ >>+#if __FDPIC__ >>+      { >>+       volatile struct funcdesc_t funcdesc; >>+       funcdesc.ptr = UCB_PR_ADDR (ucbp); >>+       funcdesc.got = UCB_PR_GOT (ucbp); >>+       pr_result = ((personality_routine) &funcdesc) >>+         (_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs); >>+      } >>+#else >>       pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) >>         (_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs); >>+#endif >>     } >>   while (pr_result == _URC_CONTINUE_UNWIND); >> >>@@ -488,13 +557,27 @@ __gnu_Unwind_Resume (_Unwind_Control_Block * >>ucbp, phase2_vrs * entry_vrs) >>     } >> >>   /* Call the cached PR.  */ >>+#if __FDPIC__ >>+  { >>+    volatile struct funcdesc_t funcdesc; >>+    funcdesc.ptr = UCB_PR_ADDR (ucbp); >>+    funcdesc.got = UCB_PR_GOT (ucbp); >>+    pr_result = ((personality_routine) &funcdesc) >>+      (_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs); >>+  } >>+#else >>   pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) >>         (_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs); >>+#endif >> >>   switch (pr_result) >>     { >>     case _URC_INSTALL_CONTEXT: >>       /* Upload the registers to enter the landing pad.  */ >>+#if __FDPIC__ >>+      /* r9 could have been lost due to PLT jump.  Restore correct >>value.  */ >>+      entry_vrs->core.r[FDPIC_REGNUM] = gnu_Unwind_Find_got (VRS_PC >>(entry_vrs)); >>+#endif >>       uw_restore_core_regs (entry_vrs, &entry_vrs->core); >> >>     case _URC_CONTINUE_UNWIND: >>@@ -586,9 +669,20 @@ __gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, >>void * trace_argument, >>         } >> >>       /* Call the pr to decide what to do.  */ >>+#if __FDPIC__ >>+      { >>+       volatile struct funcdesc_t funcdesc; >>+       funcdesc.ptr = UCB_PR_ADDR (ucbp); >>+       funcdesc.got = UCB_PR_GOT (ucbp); >>+       code = ((personality_routine) &funcdesc) >>+         (_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, >>+          ucbp, (void *) &saved_vrs); >>+      } >>+#else >>       code = ((personality_routine) UCB_PR_ADDR (ucbp)) >>         (_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, >>          ucbp, (void *) &saved_vrs); >>+#endif >>     } >>   while (code != _URC_END_OF_STACK >>          && code != _URC_FAILURE); >>diff --git a/libgcc/unwind-pe.h b/libgcc/unwind-pe.h >>index 4ed1c66..1c9dae5 100644 >>--- a/libgcc/unwind-pe.h >>+++ b/libgcc/unwind-pe.h >>@@ -262,10 +262,27 @@ read_encoded_value_with_base (unsigned char >>encoding, _Unwind_Ptr base, >> >>       if (result != 0) >>         { >>+#if __FDPIC__ >>+         /* FDPIC relative addresses imply taking the GOT address >>+            into account.  */ >>+         if ((encoding & DW_EH_PE_pcrel) && (encoding & >>DW_EH_PE_indirect)) >>+           { >>+             result += gnu_Unwind_Find_got ((_Unwind_Ptr) u); >>+             result = *(_Unwind_Internal_Ptr *) result; >>+           } >>+         else >>+           { >>+             result += ((encoding & 0x70) == DW_EH_PE_pcrel >>+                        ? (_Unwind_Internal_Ptr) u : base); >>+             if (encoding & DW_EH_PE_indirect) >>+               result = *(_Unwind_Internal_Ptr *) result; >>+           } >>+#else >>           result += ((encoding & 0x70) == DW_EH_PE_pcrel >>                      ? (_Unwind_Internal_Ptr) u : base); >>           if (encoding & DW_EH_PE_indirect) >>             result = *(_Unwind_Internal_Ptr *) result; >>+#endif >>         } >>     } >> >>diff --git a/libstdc++-v3/libsupc++/eh_personality.cc >>b/libstdc++-v3/libsupc++/eh_personality.cc >>index 35e4e46..1528ab9 100644 >>--- a/libstdc++-v3/libsupc++/eh_personality.cc >>+++ b/libstdc++-v3/libsupc++/eh_personality.cc >>@@ -93,7 +93,15 @@ get_ttype_entry (lsda_header_info *info, _uleb128_t i) >>   _Unwind_Ptr ptr; >> >>   i *= size_of_encoded_value (info->ttype_encoding); >>-  read_encoded_value_with_base (info->ttype_encoding, info->ttype_base, >>+  read_encoded_value_with_base ( >>+#if __FDPIC__ >>+                               /* Force these flags to nake sure to >>+                                  take the GOT into account.  */ >>+                               (DW_EH_PE_pcrel | DW_EH_PE_indirect), >>+#else >>+                               info->ttype_encoding, >>+#endif >>+                               info->ttype_base, >>                                 info->TType - i, &ptr); >> >>   return reinterpret_cast(ptr); >>-- >>2.6.3 >>