https://sourceware.org/bugzilla/show_bug.cgi?id=26143
Bug ID: 26143 Summary: gas generates invalid line table entry Product: binutils Version: 2.35 (HEAD) Status: NEW Severity: normal Priority: P2 Component: gas Assignee: unassigned at sourceware dot org Reporter: vries at gcc dot gnu.org Target Milestone: --- Consider 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-9 test.c -O2 -g -c -save-temps -fno-reorder-blocks-and-partition -v ... 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: ... resulting in the following line-table (readelf -wL): ... CU: ./test.c: File name Line number Starting address View Stmt test.c 5 0 x test.c 6 0 1 x test.c 8 0 2 x test.c 5 0 3 test.c 8 0x2 test.c 14 0x6 x test.c 15 0x6 1 test.c 9 0x10 x test.c 9 0x10 1 test.c 11 0x12 x test.c 11 0x12 1 test.c 12 0x16 x test.c 5 0x16 1 test.c 12 0x17 test.c 12 0x1c test.c 12 0x1c 1 ... or the last three entries in encoded form (readelf -wl): ... [0x0000007f] Special opcode 26: advance Address by 1 to 0x17 and Line by 7 to 12 [0x00000080] Special opcode 75: advance Address by 5 to 0x1c and Line by 0 to 12 [0x00000081] Extended opcode 1: End of Sequence ... According to the dwarf standard: ... 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. ... Furthermore, for special opcodes we have: ... 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 3. Append a row to the matrix using the current values of the state machine registers. ... So, we have a contradiction here. One the one hand, the end-of-sequence declares that address 0x1c is one past the byte of the last target machine instruction of the sequence. On the other hand, the special opcode declares a target instruction starting at address 0x1c, that is part of that same sequence. This is due to the .loc before the .cfi_endproc, and specifically, due to the view bit. If we drop the view bit, the .loc is ignored. The view bit is documented as: ... view value This option causes a row to be added to .debug_line in reference to the current address (which might not be the same as that of the following assembly instruction), and to associate value with the view register in the .debug_line state machine. If value is a label, both the view register and the label are set to the number of prior .loc directives at the same program location. If value is the literal 0, the view register is set to zero, and the assembler asserts that there aren’t any prior .loc directives at the same program location. If value is the literal -0, the assembler arrange for the view register to be reset in this row, even if there are prior .loc directives at the same program location. ... I cannot tell from the formulation "in reference to the current address (which might not be the same as that of the following assembly instruction)" whether this particular instance of .loc usage is valid. -- You are receiving this mail because: You are on the CC list for the bug.