When doing a build from current trunk, I get the following in the .debug_line section of build/x86_64-pc-linux-gnu/libgcc/libgcc_s.so.1: ... [0x000006f5] Special opcode 75: advance Address by 5 to 0x2faa and Line by 0 to 246 [0x000006f6] Advance PC by 0 to 0x2faa [0x000006f8] Extended opcode 1: End of Sequence ... This is nonsensical dwarf: both the special opcode and the End-Of-Sequence declare a row in the matrix, each with the same address. The special opcode declares a target instruction at that address. The End-of-Sequence declares that the sequence ends before that address. It's a contradiction that the target instruction is both part of the sequence (according to Copy) and not part of the sequence (according to End-of-Sequence). [ Relevant dwarf standard bits: end_sequence: A boolean indicating that the current address is that of the first byte after the end of a sequence of target machine instructions. end_sequence terminates a sequence of lines; therefore other information in the same row is not meaningful. Special Opcodes Each ubyte special opcode has the following effect on the state machine: 1. Add a signed integer to the line register. 2. Modify the operation pointer by incrementing the address and op_index registers as described below. 3. Append a row to the matrix using the current values of the state machine registers. DW_LNE_end_sequence: The DW_LNE_end_sequence opcode takes no operands. It sets the end_sequence register of the state machine to “true” and appends a row to the matrix using the current values of the state-machine registers. Then it resets the registers to the initial values specified above (see Section 6.2.2). Every line number program sequence must end with a DW_LNE_end_sequence instruction which creates a row whose address is that of the byte after the last target machine instruction of the sequence. ]
I can track this down to build/x86_64-pc-linux-gnu/libgcc/_absvsi2_s.o ... [0x00000116] Special opcode 75: advance Address by 5 to 0xa and Line by 0 to 246 [0x00000117] Advance PC by 0 to 0xa [0x00000119] Extended opcode 1: End of Sequence ... and using -save-temps I get the corresponding .s file: ... .section .text.unlikely .cfi_startproc .type __absvsi2.cold, @function __absvsi2.cold: .LFSB26: .L12: .cfi_def_cfa_offset 16 .loc 1 246 5 is_stmt 1 view .LVU17 call abort@PLT .LVL7: .loc 1 246 5 is_stmt 0 view .LVU33 .cfi_endproc .LFE26: ... I think this is due to the last .loc. I'm not sure if it makes sense to declare a .loc after a non-returning insn.
Created attachment 48702 [details] _absvsi2_s.c To reproduce: ... $ gcc -O2 -g -fpic -mlong-double-80 -fcf-protection -mshstk -fbuilding-libgcc -fno-stack-protector -o _absvsi2_s.o -c _absvsi2_s.c -save-temps ...
Gdb currently silently ignores the offending entry. I've filed a gdb PR, PR26092 - "Complain about contradictory DW_LNE_end_sequence marker" to complain about this ( https://sourceware.org/bugzilla/show_bug.cgi?id=26092 ).
(In reply to Tom de Vries from comment #2) > Created attachment 48702 [details] > _absvsi2_s.c > > To reproduce: > ... > $ gcc -O2 -g -fpic -mlong-double-80 -fcf-protection -mshstk > -fbuilding-libgcc -fno-stack-protector -o _absvsi2_s.o -c _absvsi2_s.c > -save-temps > ... Minimal example test.c: ... #include <stdlib.h> int foo (int a) { int w = a; if (a < 0) w = -(unsigned int) a; if (w < 0) abort (); return w; } ... Compiled like this: ... $ gcc test.c -O2 -g -c -fno-reorder-blocks-and-partition ... resulting in test.s: ... .file "test.c" .text .Ltext0: .p2align 4 .globl foo .type foo, @function foo: .LVL0: .LFB13: .file 1 "test.c" .loc 1 5 1 view -0 .cfi_startproc .loc 1 6 3 view .LVU1 .loc 1 8 3 view .LVU2 .loc 1 5 1 is_stmt 0 view .LVU3 movl %edi, %eax .loc 1 8 6 view .LVU4 testl %edi, %edi js .L7 .LVL1: .L2: .loc 1 14 4 is_stmt 1 view .LVU5 .loc 1 15 1 is_stmt 0 view .LVU6 ret .LVL2: .p2align 4,,10 .p2align 3 .L7: .loc 1 9 5 is_stmt 1 view .LVU7 .loc 1 9 9 is_stmt 0 view .LVU8 negl %eax .LVL3: .loc 1 11 3 is_stmt 1 view .LVU9 .loc 1 11 6 is_stmt 0 view .LVU10 testl %eax, %eax jns .L2 .loc 1 12 5 is_stmt 1 view .LVU11 .LVL4: .loc 1 5 1 is_stmt 0 view .LVU12 pushq %rax .cfi_def_cfa_offset 16 .loc 1 12 5 view .LVU13 call abort .LVL5: .loc 1 12 5 view .LVU14 .cfi_endproc .LFE13: .size foo, .-foo .Letext0: ...
This seems to be var-track related. Before var-track we have: ... (debug_insn 23 41 24 5 (debug_marker) "test2.c":12:5 -1 (nil)) (call_insn 24 23 25 5 (call (mem:QI (symbol_ref:DI ("abort") [flags 0x41] <function_decl 0x7\ f376428b600 abort>) [0 __builtin_abort S1 A8]) (const_int 0 [0])) "test2.c":12:5 795 {*call} (expr_list:REG_CALL_DECL (symbol_ref:DI ("abort") [flags 0x41] <function_decl 0x7f37642\ 8b600 abort>) (expr_list:REG_ARGS_SIZE (const_int 0 [0]) (expr_list:REG_NORETURN (const_int 0 [0]) (expr_list:REG_EH_REGION (const_int 0 [0]) (nil))))) (nil)) (barrier 25 24 39) (note 39 25 0 NOTE_INSN_DELETED) ... and after: ... (call_insn:TI 24 41 80 5 (call (mem:QI (symbol_ref:DI ("abort") [flags 0x41] <function_decl 0x7fc0f7701000 abort>) [0 __builtin_abort S1 A8]) (const_int 0 [0])) "test2.c":12:5 666 {*call} (expr_list:REG_CALL_ARG_LOCATION (nil) (expr_list:REG_CALL_DECL (symbol_ref:DI ("abort") [flags 0x41] <function_decl 0x7fc0f7701000 abort>) (expr_list:REG_ARGS_SIZE (const_int 0 [0]) (expr_list:REG_NORETURN (const_int 0 [0]) (expr_list:REG_EH_REGION (const_int 0 [0]) (nil)))))) (nil)) (note/c 80 24 79 (var_location a (entry_value:SI (reg:SI 5 di [ a ]))) NOTE_INSN_VAR_LOCATION) (note/c 79 80 25 (var_location w (neg:SI (entry_value:SI (reg:SI 5 di [ a ])))) NOTE_INSN_VAR_LOCATION) (barrier 25 79 39) (note 39 25 0 NOTE_INSN_DELETED) ...
A simple way of fixing this is: ... diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 899a5c0290d..4b143f6702b 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -6635,7 +6635,7 @@ add_with_sets (rtx_insn *insn, struct cselib_set *sets, int n_se ts) std::swap (mos[n1], mos[n2]); } - if (CALL_P (insn)) + if (CALL_P (insn) && ! find_reg_note (insn, REG_NORETURN, NULL)) { micro_operation mo; ... after which we have: ... .loc 1 12 5 view .LVU13 call abort .cfi_endproc ...
A bit more subtle: ... diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 899a5c0290d..f94eb38f797 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -8880,6 +8880,10 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data) if (where != EMIT_NOTE_BEFORE_INSN) { + if (CALL_P (insn) && where == EMIT_NOTE_AFTER_CALL_INSN + && find_reg_note (insn, REG_NORETURN, NULL)) + goto done; + note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn); if (where == EMIT_NOTE_AFTER_CALL_INSN) NOTE_DURING_CALL_P (note) = true; @@ -8901,6 +8905,7 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data) } NOTE_VAR_LOCATION (note) = note_vl; + done: set_dv_changed (var->dv, false); gcc_assert (var->in_changed_variables); var->in_changed_variables = false; ... which gets us: ... .loc 1 12 5 view .LVU13 call abort .LVL5: .cfi_endproc ...