With -mfentry, GCC (I've found this with Red Hat 4.7.0-5 and Red Hat 4.7.2-2 on Fedora 17) generates odd debuginfo about variable locations. Here are examples: ----- <1><9a58>: Abbrev Number: 86 (DW_TAG_subprogram) <9a59> DW_AT_external : 1 <9a59> DW_AT_name : (indirect string, offset: 0xd82): unregister_di e_notifier <9a5d> DW_AT_decl_file : 1 <9a5e> DW_AT_decl_line : 551 <9a60> DW_AT_prototyped : 1 <9a60> DW_AT_type : <0x7c> <9a64> DW_AT_low_pc : 0x740 <9a6c> DW_AT_high_pc : 0x75a <9a74> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <9a76> DW_AT_GNU_all_call_sites: 1 <9a76> DW_AT_sibling : <0x9aac> <2><9a7a>: Abbrev Number: 87 (DW_TAG_formal_parameter) <9a7b> DW_AT_name : nb <9a7e> DW_AT_decl_file : 1 <9a7f> DW_AT_decl_line : 551 <9a81> DW_AT_type : <0x2a96> <9a85> DW_AT_location : 0x172f (location list) ... 0000172f 0000000000000745 0000000000000750 (DW_OP_reg5 (rdi)) 0000172f 0000000000000750 0000000000000757 (DW_OP_reg4 (rsi)) 0000172f 0000000000000757 000000000000075a (DW_OP_GNU_entry_value: (DW_OP_reg5 (rdi)); DW_OP_stack_value) 0000172f <End of list> ----- As you can see, the location of the parameter "nb", starts from 0x745 but unregister_die_notifier() function itself starts from 0x740. ----- <1><9aac>: Abbrev Number: 86 (DW_TAG_subprogram) <9aad> DW_AT_external : 1 <9aad> DW_AT_name : (indirect string, offset: 0x321f): notify_die <9ab1> DW_AT_decl_file : 1 <9ab2> DW_AT_decl_line : 530 <9ab4> DW_AT_prototyped : 1 <9ab4> DW_AT_type : <0x7c> <9ab8> DW_AT_low_pc : 0xb0 <9ac0> DW_AT_high_pc : 0xe0 <9ac8> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <9aca> DW_AT_GNU_all_call_sites: 1 <9aca> DW_AT_sibling : <0x9b6c> <2><9ace>: Abbrev Number: 87 (DW_TAG_formal_parameter) <9acf> DW_AT_name : val <9ad3> DW_AT_decl_file : 1 <9ad4> DW_AT_decl_line : 530 <9ad6> DW_AT_type : <0x2b36> <9ada> DW_AT_location : 0x177b (location list) ... 0000177b 00000000000000b0 00000000000000cd (DW_OP_reg5 (rdi)) 0000177b 00000000000000cd 00000000000000dd (DW_OP_reg4 (rsi)) 0000177b 00000000000000dd 00000000000000e0 (DW_OP_GNU_entry_value: (DW_OP_reg5 (rdi)); DW_OP_stack_value) 0000177b <End of list> ----- However, without fentry call (notifiy_die is marked notrace), the parameter "val" location start with 0xb0, which is same as notify_die start address. URL: https://lkml.org/lkml/2012/10/3/187
Please provide preprocessed testcase and gcc options used to compile it.
That said, it can be reproduced even on: int foo (int a, int b) { asm volatile ("nop"); a = 1; return a + b; } with -g -O2 -mfentry -p -dA. The issue is that FUNCTION_PROFILER before epilogue is emitted really very early, before processing any NOTE_INSN_VAR_LOCATION that are before the first real insn. If the targetm.asm_out.function_prologue hook is the default, outputting nothing, perhaps we could consider as ugly hack to process the NOTE_INSN_VAR_LOCATION notes before any non-note insn before calling the FUNCTION_PROFILER, or, just forcefully use the function start label in dwarf2out_var_location for notes that are before first real insn, perhaps limit that to #ifdef HAVE_prologue if (HAVE_prologue) #endif to avoid damaging debug info for !HAVE_prologue targets (if there are still any).
A little longer test case (which requires a location_list rather than location for all the parameters) shows that gdb is adversely affected by this bug too; its prologue-finding is no help: % cat foo2.c int foo (int a, int b) __attribute__((noinline)); int bar (int c, int d) __attribute__((noinline)); int bar (int c, int d) { while (c-- > d++) ; } int foo (int a, int b) { asm volatile ("nop"); return bar (a, b); } int main () { return foo (7, 4); } % gcc -g -O2 -mfentry foo2.c -p % gdb a.out (gdb) break foo Breakpoint 1 at 0x400660: file foo2.c, line 11. (gdb) run Starting program: /tmp/a.out Breakpoint 1, foo (a=<optimized out>, b=<optimized out>) at foo2.c:11 11 {
I guess the most elegant solution is to have the RTL prologue start with a NOTE_INSN_PROLOGUE_START, and output the before-prologue profiler-call during the final scan of that note, just like we output the after-prologue profiler call at the final scan of NOTE_INSN_PROLOGUE_END.
Well, we can also just use the first NOTE_INSN_BASIC_BLOCK resp. NOTE_INSN_FUNCTION_BEG, whichever comes first. The bigger problem with that ia64, pa and a few other targets use both PROLOGUE_BEFORE_EPILOGUE and non-default function_prologue hook, which emits some assembly stuff (even when they HAVE_prologue). Perhaps for those targets we'd need to emit the profiler code right away, and only postpone it until the first NOTE_INSN_BASIC_BLOCK/NOTE_INSN_FUNCTION_BEG if function_prologue hook is the default.
Created attachment 29271 [details] gcc48-pr54793.patch So, e.g. this seems to work for me from quick testing. The insn chain scanning is there e.g. to emit the profiler stuff right away when final_start_function is called from output_mi_thunk on various targets.
Author: jakub Date: Fri Feb 1 16:54:14 2013 New Revision: 195669 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=195669 Log: 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. Modified: trunk/gcc/ChangeLog trunk/gcc/final.c
Fixed for 4.8+.