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.

Reply via email to