This is the mail archive of the gcc-patches@gcc.gnu.org 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]

[PATCH] Fix unwind info for i?86 set_got (PR debug/43293)


Hi!

I've noticed we generate wrong unwind info for i?86 -fpic set_got sequences.
As 4.5 now generates correct unwind info for epilogues this means we still
can't trust the unwind info (e.g. for async signal interrupted code),
even with -fasynchronous-unwind-tables.

For deep branch prediction there are 2 issues - the queued register saves
are flushed only after the whole sequence, as the whole set_got is
considered one insn, while already the called thunk clobbers %ebx and
the thunks don't have unwind info.
For non-deep branch prediction, the call acts as a push and thus
for -fomit-frame-pointer the unwind info is wrong for one insn, and
similarly queued register saves aren't flushed after the popl, but only
after the final addl.

While it would be possible to change output_set_got into a "#" insn
with define_split being regstack_complete guarded, it wouldn't solve this
completely and we'd need hacks in dwarf2out.c and final.c to handle it,
as e.g. it is undesirable to make the call an actual CALL_INSN.
The following patch handles this in the backend, by calling
dwarf2out_frame_debug with made up insns that represent what is interesting
from unwind info POV.  Unwind info for the thunks is only handled for cfi
directive unwind info ATM, handling it for manual .eh_frame would be more
difficult and would need at least some dwarf2out.c changes.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2010-03-09  Jakub Jelinek  <jakub@redhat.com>

	PR debug/43293
	* config/i386/t-i386 (i386.o): Depend on debug.h and dwarf2out.h.
	* config/i386/i386.c: Include debug.h and dwarf2out.h.
	(ix86_file_end): If dwarf2out_do_cfi_asm (), emit .cfi_startproc
	and .cfi_endproc around the pic thunks.
	(output_set_got): For TARGET_DEEP_BRANCH_PREDICTION pic, ensure
	all queued unwind info register saves are saved before the call.
	For !TARGET_DEEP_BRANCH_PREDICTION pic, ensure the call is
	considered as sp-=4 for unwind info and the pop as sp+=4 which
	also clobbers dest, but doesn't actually restore it.

--- gcc/config/i386/t-i386.jj	2009-11-23 13:04:31.000000000 +0100
+++ gcc/config/i386/t-i386	2009-11-23 13:04:31.000000000 +0100
@@ -23,7 +23,7 @@ i386.o: $(CONFIG_H) $(SYSTEM_H) coretype
   $(RECOG_H) $(EXPR_H) $(OPTABS_H) toplev.h $(BASIC_BLOCK_H) \
   $(GGC_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h $(CGRAPH_H) \
   $(TREE_GIMPLE_H) $(DWARF2_H) $(DF_H) tm-constrs.h $(PARAMS_H) \
-  i386-builtin-types.inc
+  i386-builtin-types.inc debug.h dwarf2out.h
 
 i386-c.o: $(srcdir)/config/i386/i386-c.c \
   $(srcdir)/config/i386/i386-protos.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
--- gcc/config/i386/i386.c.jj	2010-03-01 16:31:50.000000000 +0100
+++ gcc/config/i386/i386.c	2010-03-08 21:56:51.000000000 +0100
@@ -53,6 +53,8 @@ along with GCC; see the file COPYING3.  
 #include "tm-constrs.h"
 #include "params.h"
 #include "cselib.h"
+#include "debug.h"
+#include "dwarf2out.h"
 
 static rtx legitimize_dllimport_symbol (rtx, bool);
 
@@ -7584,6 +7586,9 @@ ix86_file_end (void)
   for (regno = 0; regno < 8; ++regno)
     {
       char name[32];
+#ifdef DWARF2_UNWIND_INFO
+      bool do_cfi;
+#endif
 
       if (! ((pic_labels_used >> regno) & 1))
 	continue;
@@ -7629,10 +7634,19 @@ ix86_file_end (void)
 	  ASM_OUTPUT_LABEL (asm_out_file, name);
 	}
 
+#ifdef DWARF2_UNWIND_INFO
+      do_cfi = dwarf2out_do_cfi_asm ();
+      if (do_cfi)
+	fprintf (asm_out_file, "\t.cfi_startproc\n");
+#endif
       xops[0] = gen_rtx_REG (Pmode, regno);
       xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
       output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops);
       output_asm_insn ("ret", xops);
+#ifdef DWARF2_UNWIND_INFO
+      if (do_cfi)
+	fprintf (asm_out_file, "\t.cfi_endproc\n");
+#endif
     }
 
   if (NEED_INDICATE_EXEC_STACK)
@@ -7673,7 +7687,24 @@ output_set_got (rtx dest, rtx label ATTR
       if (!flag_pic)
 	output_asm_insn ("mov%z0\t{%2, %0|%0, %2}", xops);
       else
-	output_asm_insn ("call\t%a2", xops);
+	{
+	  output_asm_insn ("call\t%a2", xops);
+#ifdef DWARF2_UNWIND_INFO
+	  /* The call to next label acts as a push.  */
+	  if (dwarf2out_do_frame ())
+	    {
+	      rtx insn;
+	      start_sequence ();
+	      insn = emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+					     gen_rtx_PLUS (Pmode,
+							   stack_pointer_rtx,
+							   GEN_INT (-4))));
+	      RTX_FRAME_RELATED_P (insn) = 1;
+	      dwarf2out_frame_debug (insn, true);
+	      end_sequence ();
+	    }
+#endif
+	}
 
 #if TARGET_MACHO
       /* Output the Mach-O "canonical" label name ("Lxx$pb") here too.  This
@@ -7686,7 +7717,27 @@ output_set_got (rtx dest, rtx label ATTR
 				 CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
 
       if (flag_pic)
-	output_asm_insn ("pop%z0\t%0", xops);
+	{
+	  output_asm_insn ("pop%z0\t%0", xops);
+#ifdef DWARF2_UNWIND_INFO
+	  /* The pop is a pop and clobbers dest, but doesn't restore it
+	     for unwind info purposes.  */
+	  if (dwarf2out_do_frame ())
+	    {
+	      rtx insn;
+	      start_sequence ();
+	      insn = emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx));
+	      dwarf2out_frame_debug (insn, true);
+	      insn = emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+					     gen_rtx_PLUS (Pmode,
+							   stack_pointer_rtx,
+							   GEN_INT (4))));
+	      RTX_FRAME_RELATED_P (insn) = 1;
+	      dwarf2out_frame_debug (insn, true);
+	      end_sequence ();
+	    }
+#endif
+	}
     }
   else
     {
@@ -7694,6 +7745,18 @@ output_set_got (rtx dest, rtx label ATTR
       get_pc_thunk_name (name, REGNO (dest));
       pic_labels_used |= 1 << REGNO (dest);
 
+#ifdef DWARF2_UNWIND_INFO
+      /* Ensure all queued register saves are flushed before the
+	 call.  */
+      if (dwarf2out_do_frame ())
+	{
+	  rtx insn;
+	  start_sequence ();
+	  insn = emit_barrier ();
+	  end_sequence ();
+	  dwarf2out_frame_debug (insn, false);
+	}
+#endif
       xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
       xops[2] = gen_rtx_MEM (QImode, xops[2]);
       output_asm_insn ("call\t%X2", xops);

	Jakub


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