OpenMP/Fortran: Fix gfortran.dg/gomp/is_device_ptr-2.f90
[gcc.git] / libgcc / unwind-dw2.c
index e474433603105ec414ecf3e846569be28f7c4b3c..41af7e23f47602ec9a62673ad2c0f5d9e0a5e943 100644 (file)
@@ -1,5 +1,5 @@
 /* DWARF2 exception handling and frame unwind runtime interface routines.
-   Copyright (C) 1997-2014 Free Software Foundation, Inc.
+   Copyright (C) 1997-2021 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
 #define PRE_GCC3_DWARF_FRAME_REGISTERS __LIBGCC_DWARF_FRAME_REGISTERS__
 #endif
 
-#ifndef DWARF_REG_TO_UNWIND_COLUMN
-#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
-#endif
-
 /* ??? For the public function interfaces, we tend to gcc_assert that the
    column numbers are in range.  For the dwarf2 unwind info this does happen,
    although so far in a case that doesn't actually matter.
@@ -140,6 +136,9 @@ struct _Unwind_Context
 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
   /* Context which has version/args_size/by_value fields.  */
 #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+  /* Bit reserved on AArch64, return address has been signed with A or B
+     key.  */
+#define RA_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
   _Unwind_Word flags;
   /* 0 for now, can be increased when further fields are added to
      struct _Unwind_Context.  */
@@ -218,20 +217,20 @@ _Unwind_IsExtendedContext (struct _Unwind_Context *context)
          || (context->flags & EXTENDED_CONTEXT_BIT));
 }
 \f
-/* Get the value of register INDEX as saved in CONTEXT.  */
+/* Get the value of register REGNO as saved in CONTEXT.  */
 
 inline _Unwind_Word
-_Unwind_GetGR (struct _Unwind_Context *context, int index)
+_Unwind_GetGR (struct _Unwind_Context *context, int regno)
 {
-  int size;
+  int size, index;
   _Unwind_Context_Reg_Val val;
 
 #ifdef DWARF_ZERO_REG
-  if (index == DWARF_ZERO_REG)
+  if (regno == DWARF_ZERO_REG)
     return 0;
 #endif
 
-  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  index = DWARF_REG_TO_UNWIND_COLUMN (regno);
   gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
   size = dwarf_reg_size_table[index];
   val = context->reg[index];
@@ -239,6 +238,14 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index)
   if (_Unwind_IsExtendedContext (context) && context->by_value[index])
     return _Unwind_Get_Unwind_Word (val);
 
+#ifdef DWARF_LAZY_REGISTER_VALUE
+  {
+    _Unwind_Word value;
+    if (DWARF_LAZY_REGISTER_VALUE (regno, &value))
+      return value;
+  }
+#endif
+
   /* This will segfault if the register hasn't been saved.  */
   if (size == sizeof(_Unwind_Ptr))
     return * (_Unwind_Ptr *) (_Unwind_Internal_Ptr) val;
@@ -496,6 +503,11 @@ extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
          fs->signal_frame = 1;
          aug += 1;
        }
+      /* aarch64 B-key pointer authentication.  */
+      else if (aug[0] == 'B')
+       {
+         aug += 1;
+      }
 
       /* Otherwise we have an unknown augmentation string.
         Bail unless we saw a 'z' prefix.  */
@@ -1189,6 +1201,11 @@ execute_cfa_program (const unsigned char *insn_ptr,
          break;
 
        case DW_CFA_GNU_window_save:
+#if defined (__aarch64__) && !defined (__ILP32__)
+         /* This CFA is multiplexed with Sparc.  On AArch64 it's used to toggle
+            return address signing status.  */
+         fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
+#else
          /* ??? Hardcoded for SPARC register window configuration.  */
          if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
            for (reg = 16; reg < 32; ++reg)
@@ -1196,6 +1213,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
                fs->regs.reg[reg].how = REG_SAVED_OFFSET;
                fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
              }
+#endif
          break;
 
        case DW_CFA_GNU_args_size:
@@ -1517,10 +1535,18 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
        stack frame.  */
     context->ra = 0;
   else
-    /* Compute the return address now, since the return address column
-       can change from frame to frame.  */
-    context->ra = __builtin_extract_return_addr
-      (_Unwind_GetPtr (context, fs->retaddr_column));
+    {
+      /* Compute the return address now, since the return address column
+        can change from frame to frame.  */
+      void *ret_addr;
+#ifdef MD_DEMANGLE_RETURN_ADDR
+      _Unwind_Word ra = _Unwind_GetGR (context, fs->retaddr_column);
+      ret_addr = MD_DEMANGLE_RETURN_ADDR (context, fs, ra);
+#else
+      ret_addr = _Unwind_GetPtr (context, fs->retaddr_column);
+#endif
+      context->ra = __builtin_extract_return_addr (ret_addr);
+    }
 }
 
 static void
@@ -1614,14 +1640,18 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
 
 /* Install TARGET into CURRENT so that we can return to it.  This is a
    macro because __builtin_eh_return must be invoked in the context of
-   our caller.  */
+   our caller.  FRAMES is a number of frames to be unwind.
+   _Unwind_Frames_Extra is a macro to do additional work during unwinding
+   if needed, for example shadow stack pointer adjustment for Intel CET
+   technology.  */
 
-#define uw_install_context(CURRENT, TARGET)                            \
+#define uw_install_context(CURRENT, TARGET, FRAMES)                    \
   do                                                                   \
     {                                                                  \
       long offset = uw_install_context_1 ((CURRENT), (TARGET));                \
       void *handler = __builtin_frob_return_addr ((TARGET)->ra);       \
       _Unwind_DebugHook ((TARGET)->cfa, handler);                      \
+      _Unwind_Frames_Extra (FRAMES);                                   \
       __builtin_eh_return (offset, handler);                           \
     }                                                                  \
   while (0)