public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-4979] Revert "libgcc: Specialize execute_cfa_program in DWARF unwinder for alignments"
@ 2023-01-03 15:47 Florian Weimer
  0 siblings, 0 replies; only message in thread
From: Florian Weimer @ 2023-01-03 15:47 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:96127a4100e8a62c3dc009b5f06199bf24275bf3

commit r13-4979-g96127a4100e8a62c3dc009b5f06199bf24275bf3
Author: Florian Weimer <fweimer@redhat.com>
Date:   Tue Jan 3 16:47:31 2023 +0100

    Revert "libgcc: Specialize execute_cfa_program in DWARF unwinder for alignments"
    
    This reverts commit cb775ecd6e437de8fdba9a3f173f3787e90e98f2.

Diff:
---
 gcc/c-family/c-cppbuiltin.cc    |   2 -
 libgcc/unwind-dw2-execute_cfa.h | 322 ----------------------------------------
 libgcc/unwind-dw2.c             | 319 +++++++++++++++++++++++++++++++++++----
 3 files changed, 289 insertions(+), 354 deletions(-)

diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index ddfd63b8eb9..011478c88da 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -1527,8 +1527,6 @@ c_cpp_builtins (cpp_reader *pfile)
 	  builtin_define_with_int_value ("__LIBGCC_DWARF_REG_SIZES_CONSTANT__",
 					 value);
       }
-      builtin_define_with_int_value ("__LIBGCC_DWARF_CIE_DATA_ALIGNMENT__",
-				     DWARF_CIE_DATA_ALIGNMENT);
 #ifdef EH_RETURN_STACKADJ_RTX
       cpp_define (pfile, "__LIBGCC_EH_RETURN_STACKADJ_RTX__");
 #endif
diff --git a/libgcc/unwind-dw2-execute_cfa.h b/libgcc/unwind-dw2-execute_cfa.h
deleted file mode 100644
index dd97b786668..00000000000
--- a/libgcc/unwind-dw2-execute_cfa.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/* DWARF2 exception handling CFA execution engine.
-   Copyright (C) 1997-2022 Free Software Foundation, Inc.
-
-   This file is part of GCC.
-
-   GCC is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3, or (at your option)
-   any later version.
-
-   GCC is distributed in the hope that it will be useful, but WITHOUT
-   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
-   License for more details.
-
-   Under Section 7 of GPL version 3, you are granted additional
-   permissions described in the GCC Runtime Library Exception, version
-   3.1, as published by the Free Software Foundation.
-
-   You should have received a copy of the GNU General Public License and
-   a copy of the GCC Runtime Library Exception along with this program;
-   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-/* This file is included from unwind-dw2.c to specialize the code for certain
-   values of DATA_ALIGN and CODE_ALIGN.  These macros must be defined prior to
-   including this file.  */
-
-{
-  struct frame_state_reg_info *unused_rs = NULL;
-
-  /* Don't allow remember/restore between CIE and FDE programs.  */
-  fs->regs.prev = NULL;
-
-  /* The comparison with the return address uses < rather than <= because
-     we are only interested in the effects of code before the call; for a
-     noreturn function, the return address may point to unrelated code with
-     a different stack configuration that we are not interested in.  We
-     assume that the call itself is unwind info-neutral; if not, or if
-     there are delay instructions that adjust the stack, these must be
-     reflected at the point immediately before the call insn.
-     In signal frames, return address is after last completed instruction,
-     so we add 1 to return address to make the comparison <=.  */
-  while (insn_ptr < insn_end
-	 && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
-    {
-      unsigned char insn = *insn_ptr++;
-      _uleb128_t reg, utmp;
-      _sleb128_t offset, stmp;
-
-      if ((insn & 0xc0) == DW_CFA_advance_loc)
-	fs->pc += (insn & 0x3f) * CODE_ALIGN;
-      else if ((insn & 0xc0) == DW_CFA_offset)
-	{
-	  reg = insn & 0x3f;
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  offset = (_Unwind_Sword) utmp * DATA_ALIGN;
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    {
-	      fs->regs.how[reg] = REG_SAVED_OFFSET;
-	      fs->regs.reg[reg].loc.offset = offset;
-	    }
-	}
-      else if ((insn & 0xc0) == DW_CFA_restore)
-	{
-	  reg = insn & 0x3f;
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    fs->regs.how[reg] = REG_UNSAVED;
-	}
-      else switch (insn)
-	{
-	case DW_CFA_set_loc:
-	  {
-	    _Unwind_Ptr pc;
-
-	    insn_ptr = read_encoded_value (context, fs->fde_encoding,
-					   insn_ptr, &pc);
-	    fs->pc = (void *) pc;
-	  }
-	  break;
-
-	case DW_CFA_advance_loc1:
-	  fs->pc += read_1u (insn_ptr) * CODE_ALIGN;
-	  insn_ptr += 1;
-	  break;
-	case DW_CFA_advance_loc2:
-	  fs->pc += read_2u (insn_ptr) * CODE_ALIGN;
-	  insn_ptr += 2;
-	  break;
-	case DW_CFA_advance_loc4:
-	  fs->pc += read_4u (insn_ptr) * CODE_ALIGN;
-	  insn_ptr += 4;
-	  break;
-
-	case DW_CFA_offset_extended:
-	  insn_ptr = read_uleb128 (insn_ptr, &reg);
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  offset = (_Unwind_Sword) utmp * DATA_ALIGN;
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    {
-	      fs->regs.how[reg] = REG_SAVED_OFFSET;
-	      fs->regs.reg[reg].loc.offset = offset;
-	    }
-	  break;
-
-	case DW_CFA_restore_extended:
-	  insn_ptr = read_uleb128 (insn_ptr, &reg);
-	  /* FIXME, this is wrong; the CIE might have said that the
-	     register was saved somewhere.  */
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    fs->regs.how[reg] = REG_UNSAVED;
-	  break;
-
-	case DW_CFA_same_value:
-	  insn_ptr = read_uleb128 (insn_ptr, &reg);
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    fs->regs.how[reg] = REG_UNSAVED;
-	  break;
-
-	case DW_CFA_undefined:
-	  insn_ptr = read_uleb128 (insn_ptr, &reg);
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    fs->regs.how[reg] = REG_UNDEFINED;
-	  break;
-
-	case DW_CFA_nop:
-	  break;
-
-	case DW_CFA_register:
-	  {
-	    _uleb128_t reg2;
-	    insn_ptr = read_uleb128 (insn_ptr, &reg);
-	    insn_ptr = read_uleb128 (insn_ptr, &reg2);
-	    reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	    if (UNWIND_COLUMN_IN_RANGE (reg))
-	      {
-		fs->regs.how[reg] = REG_SAVED_REG;
-	        fs->regs.reg[reg].loc.reg = (_Unwind_Word)reg2;
-	      }
-	  }
-	  break;
-
-	case DW_CFA_remember_state:
-	  {
-	    struct frame_state_reg_info *new_rs;
-	    if (unused_rs)
-	      {
-		new_rs = unused_rs;
-		unused_rs = unused_rs->prev;
-	      }
-	    else
-	      new_rs = alloca (sizeof (struct frame_state_reg_info));
-
-	    *new_rs = fs->regs;
-	    fs->regs.prev = new_rs;
-	  }
-	  break;
-
-	case DW_CFA_restore_state:
-	  {
-	    struct frame_state_reg_info *old_rs = fs->regs.prev;
-	    fs->regs = *old_rs;
-	    old_rs->prev = unused_rs;
-	    unused_rs = old_rs;
-	  }
-	  break;
-
-	case DW_CFA_def_cfa:
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  fs->regs.cfa_offset = (_Unwind_Word)utmp;
-	  fs->regs.cfa_how = CFA_REG_OFFSET;
-	  break;
-
-	case DW_CFA_def_cfa_register:
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
-	  fs->regs.cfa_how = CFA_REG_OFFSET;
-	  break;
-
-	case DW_CFA_def_cfa_offset:
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  fs->regs.cfa_offset = utmp;
-	  /* cfa_how deliberately not set.  */
-	  break;
-
-	case DW_CFA_def_cfa_expression:
-	  fs->regs.cfa_exp = insn_ptr;
-	  fs->regs.cfa_how = CFA_EXP;
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  insn_ptr += utmp;
-	  break;
-
-	case DW_CFA_expression:
-	  insn_ptr = read_uleb128 (insn_ptr, &reg);
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    {
-	      fs->regs.how[reg] = REG_SAVED_EXP;
-	      fs->regs.reg[reg].loc.exp = insn_ptr;
-	    }
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  insn_ptr += utmp;
-	  break;
-
-	  /* Dwarf3.  */
-	case DW_CFA_offset_extended_sf:
-	  insn_ptr = read_uleb128 (insn_ptr, &reg);
-	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
-	  offset = stmp * DATA_ALIGN;
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    {
-	      fs->regs.how[reg] = REG_SAVED_OFFSET;
-	      fs->regs.reg[reg].loc.offset = offset;
-	    }
-	  break;
-
-	case DW_CFA_def_cfa_sf:
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
-	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
-	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
-	  fs->regs.cfa_how = CFA_REG_OFFSET;
-	  fs->regs.cfa_offset *= DATA_ALIGN;
-	  break;
-
-	case DW_CFA_def_cfa_offset_sf:
-	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
-	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
-	  fs->regs.cfa_offset *= DATA_ALIGN;
-	  /* cfa_how deliberately not set.  */
-	  break;
-
-	case DW_CFA_val_offset:
-	  insn_ptr = read_uleb128 (insn_ptr, &reg);
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  offset = (_Unwind_Sword) utmp * DATA_ALIGN;
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    {
-	      fs->regs.how[reg] = REG_SAVED_VAL_OFFSET;
-	      fs->regs.reg[reg].loc.offset = offset;
-	    }
-	  break;
-
-	case DW_CFA_val_offset_sf:
-	  insn_ptr = read_uleb128 (insn_ptr, &reg);
-	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
-	  offset = stmp * DATA_ALIGN;
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    {
-	      fs->regs.how[reg] = REG_SAVED_VAL_OFFSET;
-	      fs->regs.reg[reg].loc.offset = offset;
-	    }
-	  break;
-
-	case DW_CFA_val_expression:
-	  insn_ptr = read_uleb128 (insn_ptr, &reg);
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    {
-	      fs->regs.how[reg] = REG_SAVED_VAL_EXP;
-	      fs->regs.reg[reg].loc.exp = insn_ptr;
-	    }
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  insn_ptr += utmp;
-	  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.  */
-	  reg = DWARF_REGNUM_AARCH64_RA_STATE;
-	  gcc_assert (fs->regs.how[reg] == REG_UNSAVED);
-	  fs->regs.reg[reg].loc.offset ^= 1;
-#else
-	  /* ??? Hardcoded for SPARC register window configuration.  */
-	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
-	    for (reg = 16; reg < 32; ++reg)
-	      {
-		fs->regs.how[reg] = REG_SAVED_OFFSET;
-		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
-	      }
-#endif
-	  break;
-
-	case DW_CFA_GNU_args_size:
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  context->args_size = (_Unwind_Word)utmp;
-	  break;
-
-	case DW_CFA_GNU_negative_offset_extended:
-	  /* Obsoleted by DW_CFA_offset_extended_sf, but used by
-	     older PowerPC code.  */
-	  insn_ptr = read_uleb128 (insn_ptr, &reg);
-	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
-	  offset = (_Unwind_Word) utmp * DATA_ALIGN;
-	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
-	  if (UNWIND_COLUMN_IN_RANGE (reg))
-	    {
-	      fs->regs.how[reg] = REG_SAVED_OFFSET;
-	      fs->regs.reg[reg].loc.offset = -offset;
-	    }
-	  break;
-
-	default:
-	  gcc_unreachable ();
-	}
-    }
-}
-
-#undef DATA_ALIGN
-#undef CODE_ALIGN
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index 792338c1e38..c370121bb29 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -960,43 +960,302 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
    instruction sequence to decode, current register information and
    CIE info, and the PC range to evaluate.  */
 
-static void  __attribute__ ((__noinline__))
-execute_cfa_program_generic (const unsigned char *insn_ptr,
-			     const unsigned char *insn_end,
-			     struct _Unwind_Context *context,
-			     _Unwind_FrameState *fs)
-{
-#define DATA_ALIGN fs->data_align
-#define CODE_ALIGN fs->code_align
-#include "unwind-dw2-execute_cfa.h"
-}
-
-static inline void
-execute_cfa_program_specialized (const unsigned char *insn_ptr,
-				 const unsigned char *insn_end,
-				 struct _Unwind_Context *context,
-				 _Unwind_FrameState *fs)
-{
-#define DATA_ALIGN __LIBGCC_DWARF_CIE_DATA_ALIGNMENT__
-  /* GCC always uses 1 even on architectures with a fixed instruction
-     width.  */
-#define CODE_ALIGN 1
-#include "unwind-dw2-execute_cfa.h"
-}
-
 static void
 execute_cfa_program (const unsigned char *insn_ptr,
 		     const unsigned char *insn_end,
 		     struct _Unwind_Context *context,
 		     _Unwind_FrameState *fs)
 {
-  if (fs->data_align == __LIBGCC_DWARF_CIE_DATA_ALIGNMENT__
-      && fs->code_align == 1)
-    execute_cfa_program_specialized (insn_ptr, insn_end, context, fs);
-  else
-    execute_cfa_program_generic (insn_ptr, insn_end, context, fs);
-}
+  struct frame_state_reg_info *unused_rs = NULL;
+
+  /* Don't allow remember/restore between CIE and FDE programs.  */
+  fs->regs.prev = NULL;
+
+  /* The comparison with the return address uses < rather than <= because
+     we are only interested in the effects of code before the call; for a
+     noreturn function, the return address may point to unrelated code with
+     a different stack configuration that we are not interested in.  We
+     assume that the call itself is unwind info-neutral; if not, or if
+     there are delay instructions that adjust the stack, these must be
+     reflected at the point immediately before the call insn.
+     In signal frames, return address is after last completed instruction,
+     so we add 1 to return address to make the comparison <=.  */
+  while (insn_ptr < insn_end
+	 && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
+    {
+      unsigned char insn = *insn_ptr++;
+      _uleb128_t reg, utmp;
+      _sleb128_t offset, stmp;
+
+      if ((insn & 0xc0) == DW_CFA_advance_loc)
+	fs->pc += (insn & 0x3f) * fs->code_align;
+      else if ((insn & 0xc0) == DW_CFA_offset)
+	{
+	  reg = insn & 0x3f;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.how[reg] = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	    }
+	}
+      else if ((insn & 0xc0) == DW_CFA_restore)
+	{
+	  reg = insn & 0x3f;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    fs->regs.how[reg] = REG_UNSAVED;
+	}
+      else switch (insn)
+	{
+	case DW_CFA_set_loc:
+	  {
+	    _Unwind_Ptr pc;
+
+	    insn_ptr = read_encoded_value (context, fs->fde_encoding,
+					   insn_ptr, &pc);
+	    fs->pc = (void *) pc;
+	  }
+	  break;
+
+	case DW_CFA_advance_loc1:
+	  fs->pc += read_1u (insn_ptr) * fs->code_align;
+	  insn_ptr += 1;
+	  break;
+	case DW_CFA_advance_loc2:
+	  fs->pc += read_2u (insn_ptr) * fs->code_align;
+	  insn_ptr += 2;
+	  break;
+	case DW_CFA_advance_loc4:
+	  fs->pc += read_4u (insn_ptr) * fs->code_align;
+	  insn_ptr += 4;
+	  break;
+
+	case DW_CFA_offset_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.how[reg] = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	    }
+	  break;
+
+	case DW_CFA_restore_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  /* FIXME, this is wrong; the CIE might have said that the
+	     register was saved somewhere.  */
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    fs->regs.how[reg] = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_same_value:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    fs->regs.how[reg] = REG_UNSAVED;
+	  break;
+
+	case DW_CFA_undefined:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    fs->regs.how[reg] = REG_UNDEFINED;
+	  break;
+
+	case DW_CFA_nop:
+	  break;
+
+	case DW_CFA_register:
+	  {
+	    _uleb128_t reg2;
+	    insn_ptr = read_uleb128 (insn_ptr, &reg);
+	    insn_ptr = read_uleb128 (insn_ptr, &reg2);
+	    reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	    if (UNWIND_COLUMN_IN_RANGE (reg))
+	      {
+		fs->regs.how[reg] = REG_SAVED_REG;
+	        fs->regs.reg[reg].loc.reg = (_Unwind_Word)reg2;
+	      }
+	  }
+	  break;
+
+	case DW_CFA_remember_state:
+	  {
+	    struct frame_state_reg_info *new_rs;
+	    if (unused_rs)
+	      {
+		new_rs = unused_rs;
+		unused_rs = unused_rs->prev;
+	      }
+	    else
+	      new_rs = alloca (sizeof (struct frame_state_reg_info));
+
+	    *new_rs = fs->regs;
+	    fs->regs.prev = new_rs;
+	  }
+	  break;
 
+	case DW_CFA_restore_state:
+	  {
+	    struct frame_state_reg_info *old_rs = fs->regs.prev;
+	    fs->regs = *old_rs;
+	    old_rs->prev = unused_rs;
+	    unused_rs = old_rs;
+	  }
+	  break;
+
+	case DW_CFA_def_cfa:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_register:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  break;
+
+	case DW_CFA_def_cfa_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_offset = utmp;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_def_cfa_expression:
+	  fs->regs.cfa_exp = insn_ptr;
+	  fs->regs.cfa_how = CFA_EXP;
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	case DW_CFA_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.how[reg] = REG_SAVED_EXP;
+	      fs->regs.reg[reg].loc.exp = insn_ptr;
+	    }
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  break;
+
+	  /* Dwarf3.  */
+	case DW_CFA_offset_extended_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.how[reg] = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	    }
+	  break;
+
+	case DW_CFA_def_cfa_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  fs->regs.cfa_reg = (_Unwind_Word)utmp;
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_how = CFA_REG_OFFSET;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  break;
+
+	case DW_CFA_def_cfa_offset_sf:
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  fs->regs.cfa_offset = (_Unwind_Sword)stmp;
+	  fs->regs.cfa_offset *= fs->data_align;
+	  /* cfa_how deliberately not set.  */
+	  break;
+
+	case DW_CFA_val_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Sword) utmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.how[reg] = REG_SAVED_VAL_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	    }
+	  break;
+
+	case DW_CFA_val_offset_sf:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_sleb128 (insn_ptr, &stmp);
+	  offset = stmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.how[reg] = REG_SAVED_VAL_OFFSET;
+	      fs->regs.reg[reg].loc.offset = offset;
+	    }
+	  break;
+
+	case DW_CFA_val_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.how[reg] = REG_SAVED_VAL_EXP;
+	      fs->regs.reg[reg].loc.exp = insn_ptr;
+	    }
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  insn_ptr += utmp;
+	  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.  */
+	  reg = DWARF_REGNUM_AARCH64_RA_STATE;
+	  gcc_assert (fs->regs.how[reg] == REG_UNSAVED);
+	  fs->regs.reg[reg].loc.offset ^= 1;
+#else
+	  /* ??? Hardcoded for SPARC register window configuration.  */
+	  if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
+	    for (reg = 16; reg < 32; ++reg)
+	      {
+		fs->regs.how[reg] = REG_SAVED_OFFSET;
+		fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
+	      }
+#endif
+	  break;
+
+	case DW_CFA_GNU_args_size:
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  context->args_size = (_Unwind_Word)utmp;
+	  break;
+
+	case DW_CFA_GNU_negative_offset_extended:
+	  /* Obsoleted by DW_CFA_offset_extended_sf, but used by
+	     older PowerPC code.  */
+	  insn_ptr = read_uleb128 (insn_ptr, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, &utmp);
+	  offset = (_Unwind_Word) utmp * fs->data_align;
+	  reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
+	  if (UNWIND_COLUMN_IN_RANGE (reg))
+	    {
+	      fs->regs.how[reg] = REG_SAVED_OFFSET;
+	      fs->regs.reg[reg].loc.offset = -offset;
+	    }
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+}
 \f
 /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
    its caller and decode it into FS.  This function also sets the

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-01-03 15:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-03 15:47 [gcc r13-4979] Revert "libgcc: Specialize execute_cfa_program in DWARF unwinder for alignments" Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).