Patchwork If possible, include range of profile hunk before prologue in .debug_loc ranges (PR debug/54793)

login
register
mail settings
Submitter Jakub Jelinek
Date Jan. 31, 2013, 10:02 a.m.
Message ID <20130131100259.GH4385@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/217146/
State New
Headers show

Comments

Jakub Jelinek - Jan. 31, 2013, 10:02 a.m.
Hi!

The Linux kernel started (recently?) using -mfentry -p on x86_64/i686?
for some instrumentation, I believe they normally overwrite the -mfentry
prologues with nops and only when some function needs to be instrumented,
overwrite it with some call or jump.
The problem in this PR is that var-tracking notes that are meant to
live on the very first insn in the function (info about fn arguments and the
like) no longer do so, they all start after the profile prologue, so when
*gdb/systemtap or similar debug info consumer inspects debug info at the
beginning of the function, it thinks the arguments are optimized away.

This patch attempts to extend those ranges over the profiler snippet before
prologue on some targets.  I'm not doing it everywhere, because some targets
emit some assembly in their targetm.asm_out.function_prologue hook
even for HAVE_prologue, and it is likely the profiler hook isn't prepared
to handle it (think about e.g. ia64 or a few other targets).
Also, sometimes the profiler code might e.g. use push/pop in it and
invalidate potential sp based locations, either we could stop doing this
if cfun->returns_struct or cfun->static_chain_decl, but Alex argued
that it isn't any different from inline asm which uses push/pop inside of
it.  The debug info there is also correct only on the first insn in the
inline asm and right after the inline asm, not necessary inside of it,
and similarly with this patch it isn't necessarily right inside of the
profiler snippet (the kernel won't care, as it overwrites the snippet
with nops or call/jmp).

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

2013-01-31  Jakub Jelinek  <jakub@redhat.com>

	PR debug/54793
	* final.c (need_profile_function): New variable.
	(final_start_function): Drop ATTRIBUTE_UNUSED from first argument.
	If first of NOTE_INSN_BASIC_BLOCK or NOTE_INSN_FUNCTION_BEG
	is only preceeded by NOTE_INSN_VAR_LOCATION or NOTE_INSN_DELETED
	notes, targetm.asm_out.function_prologue doesn't emit anything,
	HAVE_prologue and profiler should be emitted before prologue,
	set need_profile_function instead of emitting it.
	(final_scan_insn): If need_profile_function, emit
	profile_function on the first NOTE_INSN_BASIC_BLOCK or
	NOTE_INSN_FUNCTION_BEG note.


	Jakub
Richard Henderson - Feb. 1, 2013, 4:46 p.m.
On 01/31/2013 02:02 AM, Jakub Jelinek wrote:
> 2013-01-31  Jakub Jelinek<jakub@redhat.com>
>
> 	PR debug/54793
> 	* final.c (need_profile_function): New variable.
> 	(final_start_function): Drop ATTRIBUTE_UNUSED from first argument.
> 	If first of NOTE_INSN_BASIC_BLOCK or NOTE_INSN_FUNCTION_BEG
> 	is only preceeded by NOTE_INSN_VAR_LOCATION or NOTE_INSN_DELETED
> 	notes, targetm.asm_out.function_prologue doesn't emit anything,
> 	HAVE_prologue and profiler should be emitted before prologue,
> 	set need_profile_function instead of emitting it.
> 	(final_scan_insn): If need_profile_function, emit
> 	profile_function on the first NOTE_INSN_BASIC_BLOCK or
> 	NOTE_INSN_FUNCTION_BEG note.


Ok.


r~

Patch

--- gcc/final.c.jj	2013-01-15 17:20:37.000000000 +0100
+++ gcc/final.c	2013-01-25 10:31:48.848897310 +0100
@@ -200,6 +200,9 @@  rtx current_insn_predicate;
 /* True if printing into -fdump-final-insns= dump.  */   
 bool final_insns_dump_p;
 
+/* True if profile_function should be called, but hasn't been called yet.  */
+static bool need_profile_function;
+
 static int asm_insn_count (rtx);
 static void profile_function (FILE *);
 static void profile_after_prologue (FILE *);
@@ -1668,13 +1671,15 @@  reemit_insn_block_notes (void)
      test and compare insns.  */
 
 void
-final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
+final_start_function (rtx first, FILE *file,
 		      int optimize_p ATTRIBUTE_UNUSED)
 {
   block_depth = 0;
 
   this_is_asm_operands = 0;
 
+  need_profile_function = false;
+
   last_filename = LOCATION_FILE (prologue_location);
   last_linenum = LOCATION_LINE (prologue_location);
   last_discriminator = discriminator = 0;
@@ -1695,7 +1700,41 @@  final_start_function (rtx first ATTRIBUT
   /* The Sun386i and perhaps other machines don't work right
      if the profiling code comes after the prologue.  */
   if (targetm.profile_before_prologue () && crtl->profile)
-    profile_function (file);
+    {
+      if (targetm.asm_out.function_prologue
+	  == default_function_pro_epilogue
+#ifdef HAVE_prologue
+	  && HAVE_prologue
+#endif
+	 )
+	{
+	  rtx insn;
+	  for (insn = first; insn; insn = NEXT_INSN (insn))
+	    if (!NOTE_P (insn))
+	      {
+		insn = NULL_RTX;
+		break;
+	      }
+	    else if (NOTE_KIND (insn) == NOTE_INSN_BASIC_BLOCK
+		     || NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)
+	      break;
+	    else if (NOTE_KIND (insn) == NOTE_INSN_DELETED
+		     || NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
+	      continue;
+	    else
+	      {
+		insn = NULL_RTX;
+		break;
+	      }
+
+	  if (insn)
+	    need_profile_function = true;
+	  else
+	    profile_function (file);
+	}
+      else
+	profile_function (file);
+    }
 
   /* If debugging, assign block numbers to all of the blocks in this
      function.  */
@@ -2075,6 +2114,12 @@  final_scan_insn (rtx insn, FILE *file, i
 	  break;
 
 	case NOTE_INSN_BASIC_BLOCK:
+	  if (need_profile_function)
+	    {
+	      profile_function (asm_out_file);
+	      need_profile_function = false;
+	    }
+
 	  if (targetm.asm_out.unwind_emit)
 	    targetm.asm_out.unwind_emit (asm_out_file, insn);
 
@@ -2130,6 +2175,12 @@  final_scan_insn (rtx insn, FILE *file, i
 	  break;
 
 	case NOTE_INSN_FUNCTION_BEG:
+	  if (need_profile_function)
+	    {
+	      profile_function (asm_out_file);
+	      need_profile_function = false;
+	    }
+
 	  app_disable ();
 	  if (!DECL_IGNORED_P (current_function_decl))
 	    debug_hooks->end_prologue (last_linenum, last_filename);