This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Debugging ARM noreturn functions
- From: Paul Brook <paul at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 23 Nov 2009 13:03:28 +0000
- Subject: 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
think.
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
code.
Tested on arm-none-eabi.
Applied to SVN head.
Paul
[*] Unfortunately I've lost the link to these discussions.
2009-11-23 Paul Brook <paul@codesourcery.com>
gcc/
* 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;
+ }
else
{
/* 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.