This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Debugging ARM noreturn functions

The patch below addresses a long standing issue when debugging code that 
includes noreturn functions on ARM targets.

For somewhat nebulous performance reasons, the ARM backend decides not to save 
any registers in noreturn functions. While this is technically valid, it makes 
it impossible for the debugger to unwind past this point. A common example of 
this kind of function is abort(), so this happens more than you may first 

This has been discussed a previously [*], and the compromise reached was to 
save just enough information to allow a backtrace to be obtained. In practice 
this means the link register (r14), and common frame pointer registers
(r7, r11). Conveniently the result is a more localized hack than the previous 

Tested on arm-none-eabi.
Applied to SVN head.


[*] Unfortunately I've lost the link to these discussions.

2009-11-23  Paul Brook  <>

	* config/arm/arm.c (arm_compute_save_reg0_reg12_mask): Add special
	case for noreturn functions.
	(arm_compute_save_reg_mask): Remove special noreturn handling.

Index: gcc/config/arm/arm.c
--- gcc/config/arm/arm.c	(revision 154433)
+++ gcc/config/arm/arm.c	(working copy)
@@ -12831,6 +12831,20 @@ arm_compute_save_reg0_reg12_mask (void)
 	  && crtl->uses_pic_offset_table)
 	save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
+  else if (IS_VOLATILE(func_type))
+    {
+      /* For noreturn functions we historically omitted register saves
+	 altogether.  However this really messes up debugging.  As a
+	 compromise save just the fame pointers.  Combined with the link
+	 register saved elsewhere this should be sufficient to get
+	 a backtrace.  */
+      if (frame_pointer_needed)
+	save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM;
+      if (df_regs_ever_live_p (ARM_HARD_FRAME_POINTER_REGNUM))
+	save_reg_mask |= 1 << ARM_HARD_FRAME_POINTER_REGNUM;
+      if (df_regs_ever_live_p (THUMB_HARD_FRAME_POINTER_REGNUM))
+	save_reg_mask |= 1 << THUMB_HARD_FRAME_POINTER_REGNUM;
+    }
       /* In the normal case we only need to save those registers
@@ -12917,11 +12931,6 @@ arm_compute_save_reg_mask (void)
       | (1 << LR_REGNUM)
       | (1 << PC_REGNUM);
-  /* Volatile functions do not return, so there
-     is no need to save any other registers.  */
-  if (IS_VOLATILE (func_type))
-    return save_reg_mask;
   save_reg_mask |= arm_compute_save_reg0_reg12_mask ();
   /* Decide if we need to save the link register.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]