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 <ja...@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. --- 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); Jakub