diff mbox

GCC patch committed: fix unwind info for 32-bit x86 split stack

Message ID CAOyqgcVSsB5h5+fnKvpnLgCgsWn7_-LyHj51OqkgbXD_4fnCVg@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor Jan. 31, 2017, 11:49 p.m. UTC
With a new libgo patch (waiting to be committed until we are out of
stage 4) I noticed that the runtime/pprof tests were failing about 2%
of the time on 32-bit x86.  The problem turned out to be testing
profiling with a very call-heavy benchmark.  The 32-bit x86 split
stack sequence pushes two numbers on the stack as arguments to the
__morestack function.  GCC was not generating unwind information for
those push instructions.  When the SIGPROF signal was delivered while
executing the second push instruction or the call instruction, the
unwinder would be unable to locate the PC and would crash.

Fortunately this is easy to fix as the instructions always run at the
very beginning of the function, before any stack manipulation has
occurred.  I have committed this patch to fix the problem.
Bootstrapped on x86_64-pc-linux-gnu.  Ran the Go testsuite and all the
split-stack tests in both 32-bit and 64-bit mode.

Ian

2017-01-31  Ian Lance Taylor  <iant@golang.org>

    * config/i386/i386.c (ix86_expand_split_stack_prologue): Add
    REG_ARGS_SIZE note to 32-bit push insns and call insn.
diff mbox

Patch

Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 244456)
+++ gcc/config/i386/i386.c	(working copy)
@@ -14944,6 +14944,7 @@  ix86_expand_split_stack_prologue (void)
   allocate_rtx = GEN_INT (allocate);
   args_size = crtl->args.size >= 0 ? crtl->args.size : 0;
   call_fusage = NULL_RTX;
+  rtx pop = NULL_RTX;
   if (TARGET_64BIT)
     {
       rtx reg10, reg11;
@@ -15021,13 +15022,18 @@  ix86_expand_split_stack_prologue (void)
     }
   else
     {
-      emit_insn (gen_push (GEN_INT (args_size)));
-      emit_insn (gen_push (allocate_rtx));
+      rtx_insn *insn = emit_insn (gen_push (GEN_INT (args_size)));
+      add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (UNITS_PER_WORD));
+      insn = emit_insn (gen_push (allocate_rtx));
+      add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (2 * UNITS_PER_WORD));
+      pop = GEN_INT (2 * UNITS_PER_WORD);
     }
   call_insn = ix86_expand_call (NULL_RTX, gen_rtx_MEM (QImode, fn),
 				GEN_INT (UNITS_PER_WORD), constm1_rtx,
-				NULL_RTX, false);
+				pop, false);
   add_function_usage_to (call_insn, call_fusage);
+  if (!TARGET_64BIT)
+    add_reg_note (call_insn, REG_ARGS_SIZE, GEN_INT (0));
 
   /* In order to make call/return prediction work right, we now need
      to execute a return instruction.  See