Bug 26243 - Handle line number 0 in line table produced by clang
Summary: Handle line number 0 in line table produced by clang
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: symtab (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 26538 (view as bug list)
Depends on:
Blocks:
 
Reported: 2020-07-15 13:11 UTC by Tom de Vries
Modified: 2020-09-03 05:19 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
test.cpp (534 bytes, text/x-c++src)
2020-07-15 13:11 UTC, Tom de Vries
Details
Make "set step-mode off" not stop for "no-line-info" blocks (778 bytes, patch)
2020-07-16 20:46 UTC, Pedro Alves
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tom de Vries 2020-07-15 13:11:31 UTC
Created attachment 12701 [details]
test.cpp

Consider attached test-case test.cpp, compiled like this:
...
$ clang++ --version
clang version 10.0.0 
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ clang++ -g -O0 test.cpp 
...

[ FTR, it executes like this:
...
$ ./a.out
20 23 25 26 28 30 35 60 64 65 68 70 
... ]

The following debug session derails after line 53:
...
$ gdb a.out
Reading symbols from a.out...
(gdb) b inorder
Breakpoint 1 at 0x400c40: file test.cpp, line 44.
(gdb) r
Starting program: a.out 

Breakpoint 1, inorder (root=0x6031f0 <node_array>) at test.cpp:44
44        std::vector<node *> todo;
(gdb) n
45        todo.push_back(root);
(gdb) 
46        while (!todo.empty()){
(gdb) 
47          node *curr = todo.back();
(gdb) 
48          todo.pop_back();
(gdb) 
49          if (curr->visited) {
(gdb) 
52            curr->visited = true;
(gdb) 
53            if (curr->right) { todo.push_back(curr->right); }
(gdb) 
0x0000000000400d1d in inorder (root=0x6031f0 <node_array>)
(gdb) 
Single stepping until exit from function _Z7inorderP4node,
which has no line number information.
main (argc=1, argv=0x7fffffffdce8) at test.cpp:77
77        std::cout <<  "\n";
...

In contrast, with gdb 8.3.1, we have:
...
$ gdb a.out
Reading symbols from a.out...
(gdb) b inorder
Breakpoint 1 at 0x400c40: file test.cpp, line 44.
(gdb) r
Starting program: a.out 

Breakpoint 1, inorder (root=0x6031f0 <node_array>) at test.cpp:44
44        std::vector<node *> todo;
(gdb) n
45        todo.push_back(root);
(gdb) 
46        while (!todo.empty()){
(gdb) 
47          node *curr = todo.back();
(gdb) 
48          todo.pop_back();
(gdb) 
49          if (curr->visited) {
(gdb) 
52            curr->visited = true;
(gdb) 
53            if (curr->right) { todo.push_back(curr->right); }
(gdb) 
54            todo.push_back(curr);
(gdb) 
55            if (curr->left) { todo.push_back(curr->left); }
(gdb) 
46        while (!todo.empty()){
(gdb) 
47          node *curr = todo.back();
...
Comment 1 Tom de Vries 2020-07-15 14:31:26 UTC
The inorder function runs from 400c30 to 400d80:
...
0000000000400c30 <_Z7inorderP4node>:
  400c30:       55                      push   %rbp
  400c31:       48 89 e5                mov    %rsp,%rbp
  ...
  400d79:       e8 42 fc ff ff          callq  4009c0 <_Unwind_Resume@plt>
  400d7e:       66 90                   xchg   %ax,%ax

0000000000400d80 <main>:
  400d80:       55                      push   %rbp
...
and has the following line table (skipping test.cpp for each entry):
...
      Line number    Starting address    View    Stmt
               43            0x400c30               x
               44            0x400c40               x
               45            0x400c54               x
               46            0x400c5e               x
               46            0x400c63        
               46            0x400c6c        
               46            0x400c6e        
               47            0x400c7b               x
               47            0x400c87        
               48            0x400c8b               x
               49            0x400c94               x
               49            0x400c98        
               50            0x400ca2               x
               50            0x400ca6        
               50            0x400ca8        
               50            0x400cbb        
               51            0x400cce               x
               58            0x400cd3               x
               52            0x400ce8               x
               52            0x400cec        
               53            0x400cf0               x
               53            0x400cf9        
               53            0x400cff        
               53            0x400d03        
               53            0x400d0b        
               53            0x400d18        
                0            0x400d1d        
               54            0x400d25               x
               55            0x400d2f               x
               55            0x400d38        
               55            0x400d3e        
               55            0x400d42        
               55            0x400d4a        
               55            0x400d57        
                0            0x400d5c        
               46            0x400d61               x
               58            0x400d66               x
               61            0x400d80               x
...

With gdb 8.3.1, the 0 line number entries are filtered out, because is_stmt == 0 for those entries:
...
$ gdb -batch a.out -ex "maint expand-symtabs test.cpp" -ex "maint info line-table"
INDEX    LINE ADDRESS
21         43 0x0000000000400c30
22         44 0x0000000000400c40
23         45 0x0000000000400c54
24         46 0x0000000000400c5e
25         47 0x0000000000400c7b
26         48 0x0000000000400c8b
27         49 0x0000000000400c94
28         50 0x0000000000400ca2
29         51 0x0000000000400cce
30         58 0x0000000000400cd3
31         52 0x0000000000400ce8
32         53 0x0000000000400cf0
33         54 0x0000000000400d25
34         55 0x0000000000400d2f
35         46 0x0000000000400d61
36         58 0x0000000000400d66
37         61 0x0000000000400d80
...

But with current gdb, that's no longer the case:
...
INDEX  LINE   ADDRESS            IS-STMT
50     43     0x0000000000400c30 Y 
51     44     0x0000000000400c40 Y 
52     45     0x0000000000400c54 Y 
53     46     0x0000000000400c5e Y 
54     46     0x0000000000400c63   
55     46     0x0000000000400c6c   
56     46     0x0000000000400c6e   
57     47     0x0000000000400c7b Y 
58     47     0x0000000000400c87   
59     48     0x0000000000400c8b Y 
60     49     0x0000000000400c94 Y 
61     49     0x0000000000400c98   
62     50     0x0000000000400ca2 Y 
63     50     0x0000000000400ca6   
64     50     0x0000000000400ca8   
65     50     0x0000000000400cbb   
66     51     0x0000000000400cce Y 
67     58     0x0000000000400cd3 Y 
68     52     0x0000000000400ce8 Y 
69     52     0x0000000000400cec   
70     53     0x0000000000400cf0 Y 
71     53     0x0000000000400cf9   
72     53     0x0000000000400cff   
73     53     0x0000000000400d03   
74     53     0x0000000000400d0b   
75     53     0x0000000000400d18   
76     END    0x0000000000400d1d   
77     54     0x0000000000400d25 Y 
78     55     0x0000000000400d2f Y 
79     55     0x0000000000400d38   
80     55     0x0000000000400d3e   
81     55     0x0000000000400d42   
82     55     0x0000000000400d4a   
83     55     0x0000000000400d57   
84     END    0x0000000000400d5c   
85     46     0x0000000000400d61 Y 
86     58     0x0000000000400d66 Y 
87     61     0x0000000000400d80 Y 
...

The line 0 entries are represented here as "END" or end-of-sequence, because that's the semantics of line number 0 internally in GDB.

So, the question is: what is the semantics of a line 0 entry in a .debug_line table?  The dwarf standard does not give it any special meaning.

In the llvm source code, we find in ./include/llvm/DebugInfo/DWARF/DWARFDebugLine.h:
...
    /// An unsigned integer indicating a source line number. Lines are numbered               
    /// beginning at 1. The compiler may emit the value 0 in cases where an                   
    /// instruction cannot be attributed to any source line.                                  
    uint32_t Line;
...

So, apparently clang/llvm decided on this semantics.

The easiest thing to do seems to be ignore this entry during reading:
...
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 558fad74f8..0bbd04b84f 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -20300,8 +20300,9 @@ lnp_state_machine::record_line (bool end_sequence)
          bool file_changed
            = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
          bool ignore_this_line
-           = (file_changed && !end_sequence && m_last_address == m_address
-              && !m_is_stmt && m_stmt_at_address);
+           = ((file_changed && !end_sequence && m_last_address == m_address
+               && !m_is_stmt && m_stmt_at_address)
+              || (!end_sequence && m_line == 0));
 
          if ((file_changed && !ignore_this_line) || end_sequence)
            {
...
such that we have line table:
...
47     43     0x0000000000400c30 Y 
48     44     0x0000000000400c40 Y 
49     45     0x0000000000400c54 Y 
50     46     0x0000000000400c5e Y 
51     46     0x0000000000400c63   
52     46     0x0000000000400c6c   
53     46     0x0000000000400c6e   
54     47     0x0000000000400c7b Y 
55     47     0x0000000000400c87   
56     48     0x0000000000400c8b Y 
57     49     0x0000000000400c94 Y 
58     49     0x0000000000400c98   
59     50     0x0000000000400ca2 Y 
60     50     0x0000000000400ca6   
61     50     0x0000000000400ca8   
62     50     0x0000000000400cbb   
63     51     0x0000000000400cce Y 
64     58     0x0000000000400cd3 Y 
65     52     0x0000000000400ce8 Y 
66     52     0x0000000000400cec   
67     53     0x0000000000400cf0 Y 
68     53     0x0000000000400cf9   
69     53     0x0000000000400cff   
70     53     0x0000000000400d03   
71     53     0x0000000000400d0b   
72     53     0x0000000000400d18   
73     54     0x0000000000400d25 Y 
74     55     0x0000000000400d2f Y 
75     55     0x0000000000400d38   
76     55     0x0000000000400d3e   
77     55     0x0000000000400d42   
78     55     0x0000000000400d4a   
79     55     0x0000000000400d57   
80     46     0x0000000000400d61 Y 
81     58     0x0000000000400d66 Y 
82     61     0x0000000000400d80 Y 
...
and we get the same debug session as with gdb 8.3.1.
Comment 2 Tom de Vries 2020-07-15 14:36:05 UTC
This behaviour appears to be a recent regression by commit d8cc8af6a1 "[gdb/symtab] Fix line-table end-of-sequence sorting", caused by the part of the patch that reverts this bit that was introduced by commit 3d92a3e313 "gdb: Don't reorder line table entries too much when sorting":
...
diff --git a/gdb/symtab.c b/gdb/symtab.c
index d5ba249ced..f456f4d852 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -3222,7 +3222,12 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, i
nt notcurrent)
       struct linetable_entry *last = item + len;
       item = std::upper_bound (first, last, pc, pc_compare);
       if (item != first)
-       prev = item - 1;                /* Found a matching item.  */
+       {
+         /* Found a matching item.  Skip backwards over any end of
+            sequence markers.  */
+         for (prev = item - 1; prev->line == 0 && prev != first; prev--)
+           /* Nothing.  */;
+       }
 
       /* At this point, prev points at the line whose start addr is <= pc, and
          item points at the next line.  If we ran off the end of the linetable
...

But the root cause is that clang/llvm style line number zero entries are just not handled by gdb.
Comment 3 Tom de Vries 2020-07-15 15:09:00 UTC
(In reply to Tom de Vries from comment #1)
> The line 0 entries are represented here as "END" or end-of-sequence, because
> that's the semantics of line number 0 internally in GDB.
> 
> So, the question is: what is the semantics of a line 0 entry in a
> .debug_line table?  The dwarf standard does not give it any special meaning.
> 
> In the llvm source code, we find in
> ./include/llvm/DebugInfo/DWARF/DWARFDebugLine.h:
> ...
>     /// An unsigned integer indicating a source line number. Lines are
> numbered               
>     /// beginning at 1. The compiler may emit the value 0 in cases where an 
> 
>     /// instruction cannot be attributed to any source line.                
> 
>     uint32_t Line;
> ...
> 
> So, apparently clang/llvm decided on this semantics.
> 

Correction.  I found it in the dwarf standard:
...
line:

An unsigned integer indicating a source line
number. Lines are numbered beginning at 1.
The compiler may emit the value 0 in cases
where an instruction cannot be attributed to any
source line.
...
Comment 4 Andrew Burgess 2020-07-15 15:20:54 UTC
Ignoring line number 0 while parsing is probably not the right answer.  If we do that then instruction associated with line 0 will instead be associated with the preceding line number.

This probably indicates that we should pick some other value for the end marker, -1 is probably safe enough, or given we now already carry a single bit flag for is-stmt, we could/should just add a separate flag for is-end.
Comment 5 Tom de Vries 2020-07-15 15:47:29 UTC
(In reply to Andrew Burgess from comment #4)
> Ignoring line number 0 while parsing is probably not the right answer.  If
> we do that then instruction associated with line 0 will instead be
> associated with the preceding line number.

Indeed, I found a scenario where this would make a difference: ni-stepping through line 53.

With trunk I get:
...
(gdb) 
0x0000000000400d13      53            if (curr->right) { todo.push_back(curr->right); }
(gdb) 
0x0000000000400d18      53            if (curr->right) { todo.push_back(curr->right); }
(gdb) 
0x0000000000400d1d in inorder (root=0x6031f0 <node_array>)
(gdb) 
0x0000000000400d21 in inorder (root=0x6031f0 <node_array>)
(gdb) 
...

But with the patch from comment 1, we have instead:
...
(gdb) 
0x0000000000400d13      53            if (curr->right) { todo.push_back(curr->right); }
(gdb) 
0x0000000000400d18      53            if (curr->right) { todo.push_back(curr->right); }
(gdb) 
0x0000000000400d1d      53            if (curr->right) { todo.push_back(curr->right); }
(gdb) 
0x0000000000400d21      53            if (curr->right) { todo.push_back(curr->right); }
(gdb)
...
Comment 6 Tom de Vries 2020-07-15 22:05:01 UTC
(In reply to Tom de Vries from comment #5)
> (In reply to Andrew Burgess from comment #4)
> > Ignoring line number 0 while parsing is probably not the right answer.  If
> > we do that then instruction associated with line 0 will instead be
> > associated with the preceding line number.
> 

Hmm, I think we probably want the "ignore line number 0" approach for gdb 10, to fix the regression in behaviour compared to gdb 9.2.  The scenario below doesn't work with gdb 9.2 either.

> Indeed, I found a scenario where this would make a difference: ni-stepping
> through line 53.
> 
> With trunk I get:
> ...
> (gdb) 
> 0x0000000000400d13      53            if (curr->right) {
> todo.push_back(curr->right); }
> (gdb) 
> 0x0000000000400d18      53            if (curr->right) {
> todo.push_back(curr->right); }
> (gdb) 
> 0x0000000000400d1d in inorder (root=0x6031f0 <node_array>)
> (gdb) 
> 0x0000000000400d21 in inorder (root=0x6031f0 <node_array>)
> (gdb) 
> ...
> 
> But with the patch from comment 1, we have instead:
> ...
> (gdb) 
> 0x0000000000400d13      53            if (curr->right) {
> todo.push_back(curr->right); }
> (gdb) 
> 0x0000000000400d18      53            if (curr->right) {
> todo.push_back(curr->right); }
> (gdb) 
> 0x0000000000400d1d      53            if (curr->right) {
> todo.push_back(curr->right); }
> (gdb) 
> 0x0000000000400d21      53            if (curr->right) {
> todo.push_back(curr->right); }
> (gdb)
> ...
Comment 7 Tom de Vries 2020-07-16 17:59:43 UTC
submitted patch: https://sourceware.org/pipermail/gdb-patches/2020-July/170506.html
Comment 8 Simon Marchi 2020-07-16 19:18:48 UTC
This exact problem was hit in the context of AMD's rocm-gdb [1], and we (Pedro, I and AMD devs) were in the middle of a discussion about how to handle this correctly.  I'll try to capture what came out of our discussion so far.

Let's use some simple dummy instruction / line mapping as an example:

insn1 <-> line 10
insn2 <-> line 0
insn3 <-> line 0
insn4 <-> line 20

- If an instruction is mapped to line 0, we should not hide the fact that the instruction maps to no source line.  We should not merge it with the preceding instruction's line, or something like that.

So if you stepi until insn2, or put a breakpoint on it and run, it should not appear as if you stopped at line 10.  It should appear that you stopped somewhere without source.

This should be a good motivation for compilers to emit better debug info, where all instructions are covered, where possible.

- Getting from a region with line info to a region without line info.  You are on insn1 and you do "step".  The current behavior is: it stops at insn2, where you have no source available.

On one hand, it's "correct" to stop, because we went from an instruction belonging to line 10 to an instruction not belonging to line 10.  That's the conservative thing to do.  But that's also not very useful to the average user who wants to debug at source level.

The other would be to make the step/next commands keep stepping when they go from an instruction with line info to an instruction without line info.  That is essentially the historical behavior Tom described.  In our example, doing a "step" while stopped at insn1 would step until stopped at insn4.

There is a good suggestion coming from Pedro.  There's a quite unknown setting (and with an incredibly bad name, IMO), "set step-mode":

  (gdb) help set step-mode 
  Set mode of the step operation.
  When set, doing a step over a function without debug line information
  will stop at the first instruction of that function. Otherwise, the
  function is skipped and the step command stops at a different source line.

It talks about "stepping over a function", but really it could apply here as well.  When "off" (the default), it would behave as it did historically, skipping those regions.  When "on", a step would stop at the instruction with line 0.

- Doing a step/next when stopped at an instruction with line 0

So you are stopped at insn2 and do "step", what happens?  Currently, GDB steps out of the function, we all agreed that is not really helpful.

The three possibilities are:

1. We don't have line info, so we can't step a line.  Make step act as a stepi, and next act as a nexti.
2. Treat line 0 as a real line, for this purpose.  Here, GDB would single step insn2, see that we are still at the same line as in the beginning, and single step again, to stop on insn4.
3. Tie the behavior of this to "set step-mode" as well.  When "on", act like 1, when "off", act like 2.

So with (1) the user would require two `step` to get to insn4.  With (2), it would require one.  We had arguments for and against both, which we can detail later.

[1] https://github.com/ROCm-Developer-Tools/ROCgdb
Comment 9 Pedro Alves 2020-07-16 20:46:45 UTC
Created attachment 12705 [details]
Make "set step-mode off" not stop for "no-line-info" blocks

Here's a patch implementing the idea above.
Comment 10 Pedro Alves 2020-07-16 20:51:19 UTC
With the prototype patch attached, and using Tom's testcase, I run to line 46, and then do "next".

With step-mode on, with or without the patch, we get:

 (gdb) set step-mode on
 (gdb) b 46
 Breakpoint 1 at 0x400c7b: file test.cpp, line 46.
 (gdb) r
 Starting program: /home/pedro/tmp/line0/a.out 

 Breakpoint 1, inorder (root=0x6031d0 <node_array>) at test.cpp:46
 46        while (!todo.empty()){
 (gdb) n
 0x0000000000400c80 in inorder (root=0x6031d0 <node_array>)
 (gdb) n
 0x0000000000400c84      46        while (!todo.empty()){
 (gdb) n
 0x0000000000400ca3 in inorder (root=0x6031d0 <node_array>)
 (gdb) n
 47          node *curr = todo.back();


WITHOUT the patch, and "set step-mode off" (the default), we get:

 (gdb) set step-mode off
 (gdb) b 46
 Breakpoint 1 at 0x400c7b: file test.cpp, line 46.
 (gdb) r
 Starting program: /home/pedro/tmp/line0/a.out 

 Breakpoint 1, inorder (root=0x6031d0 <node_array>) at test.cpp:46
 46        while (!todo.empty()){
 (gdb) n
 0x0000000000400c80 in inorder (root=0x6031d0 <node_array>)
 (gdb) n
 Single stepping until exit from function _Z7inorderP4node,
 which has no line number information.
 main (argc=1, argv=0x7fffffffd428) at test.cpp:77
 77        std::cout <<  "\n";
 (gdb) 


While with the patch and "set step-mode off" (the default),
we get:

 (gdb) set step-mode off
 (gdb) b 46
 Breakpoint 1 at 0x400c7b: file test.cpp, line 46.
 (gdb) r
 Starting program: /home/pedro/tmp/line0/a.out 

 Breakpoint 1, inorder (root=0x6031d0 <node_array>) at test.cpp:46
 46        while (!todo.empty()){
 (gdb) n
 47          node *curr = todo.back();


WDYT?  This seems like the ideal behavior to me.

I have no idea whether changing the line table reader to use some way other than "line == 0" to track "end-of-statement" would be invasive.
Comment 11 Pedro Alves 2020-07-16 21:18:43 UTC
I tried my patch against the testcase from Tom's proposed patch on the mailing list, and that results in:

 Running /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp ...
 FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar2, 2nd next
 KPASS: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar1_label_3 (PRMS gdb/nnnnn)
 KPASS: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar2_label_3 (PRMS gdb/nnnnn)

The FAIL is because GDB is not figuring out the length of the "bar2" function
correctly:

 (gdb) disassemble bar2
 Dump of assembler code for function bar2:
   0x00000000004004c0 <+0>:     push   %rbp
   0x00000000004004c1 <+1>:     mov    %rsp,%rbp
   0x00000000004004c4 <+4>:     mov    $0x1,%edi
   0x00000000004004c9 <+9>:     call   0x400487 <foo>
   0x00000000004004ce <+14>:    mov    $0x2,%edi
   0x00000000004004d3 <+19>:    call   0x400487 <foo>
 End of assembler dump.
 (gdb) q

So after that "next", the program stops at an address outside of the function, and so the patch's still-in-same-function logic doesn't apply.

I.e., seems like either there's a bug elsewhere, where bar2's length is determined, or the testcase has a bug.  The other two calls to foo should be part of the function too.

Interestingly, if you try to set a breakpoint just by number using
Tom's testcase (with or without his proposed fix), GDB crashes...:

 (gdb) b 54
 Aborted (core dumped)

Sigh.
Comment 12 Pedro Alves 2020-07-16 22:22:39 UTC
> I.e., seems like either there's a bug elsewhere, where bar2's length is 
> determined, or the testcase has a bug.  The other two calls to foo should be 
> part of the function too.

It's the latter - a simple typo:

diff --git c/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp w/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
index e322f777082..acf16848e82 100644
--- c/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
+++ w/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
@@ -74,7 +74,7 @@ Dwarf::assemble $asm_file {
                {external 1 flag}
                {name bar2}
                {low_pc $bar2_start addr}
-               {high_pc "$bar2_start + $main_length" addr}
+               {high_pc "$bar2_start + $bar2_length" addr}
            }
        }
     }

With that, I now get:

Running /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp ...
KPASS: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar1_label_3 (PRMS gdb/nnnnn)
KPASS: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar2_label_3 (PRMS gdb/nnnnn)

                === gdb Summary ===

# of expected passes            6
# of unknown successes          2
Comment 13 Tom de Vries 2020-07-17 15:00:24 UTC
(In reply to Pedro Alves from comment #12)
> > I.e., seems like either there's a bug elsewhere, where bar2's length is 
> > determined, or the testcase has a bug.  The other two calls to foo should be 
> > part of the function too.
> 
> It's the latter - a simple typo:
> 
> diff --git c/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
> w/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
> index e322f777082..acf16848e82 100644
> --- c/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
> +++ w/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
> @@ -74,7 +74,7 @@ Dwarf::assemble $asm_file {
>                 {external 1 flag}
>                 {name bar2}
>                 {low_pc $bar2_start addr}
> -               {high_pc "$bar2_start + $main_length" addr}
> +               {high_pc "$bar2_start + $bar2_length" addr}
>             }
>         }
>      }
> 

Sorry about that.  I've now found out that I could have used this instead:
...
                 {external 1 flag}
                 {MACRO_AT_func {bar2}}
...
Comment 14 Andrew Burgess 2020-07-20 13:00:32 UTC
I just posted this to the mailing list:
  https://sourceware.org/pipermail/gdb-patches/2020-July/170588.html

This removes the use of 0 as the end of sequence marker and replaces it with a named constant (with the value -1).
Comment 15 Pedro Alves 2020-07-20 13:15:02 UTC
Cool!

I think that for my infrun the fix, it doesn't make a difference whether "real" line 0 and end marker are ambiguous.

I'm working on extending Tom's testcase to test both "set step-mode" on and off on top of my patch.
Comment 16 cvs-commit@gcc.gnu.org 2020-07-24 22:23:10 UTC
The master branch has been updated by Tom de Vries <vries@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=876518dd0a0b6fd6f4ad0a0b247db0d6a267db27

commit 876518dd0a0b6fd6f4ad0a0b247db0d6a267db27
Author: Tom de Vries <tdevries@suse.de>
Date:   Sat Jul 25 00:23:06 2020 +0200

    [gdb/symtab] Ignore zero line table entries
    
    The DWARF standard states for the line register in the line number information
    state machine the following:
    ...
    An unsigned integer indicating a source line number.  Lines are numbered
    beginning at 1.  The compiler may emit the value 0 in cases where an
    instruction cannot be attributed to any source line.
    ...
    
    So, it's possible to have a zero line number in the DWARF line table.
    
    This is currently not handled by GDB.  The zero value is read in as any other
    line number, but internally the zero value has a special meaning:
    end-of-sequence, so the line table entry ends up having a different
    interpretation than intended in some situations.
    
    I've created a test-case where various aspects are tested, which has these 4
    interesting tests.
    
    1. Next-step through a zero-line instruction, is_stmt == 1
    gdb.dwarf2/dw2-line-number-zero.exp: bar1, 2nd next
    
    2. Next-step through a zero-line instruction, is_stmt == 0
    gdb.dwarf2/dw2-line-number-zero.exp: bar2, 2nd next
    
    3. Show source location at zero-line instruction, is_stmt == 1
    gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar1_label_3
    
    4. Show source location at zero-line instruction, is_stmt == 0
    gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar2_label_3
    
    And we have the following results:
    
    8.3.1, 9.2:
    ...
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar1, 2nd next
    PASS: gdb.dwarf2/dw2-line-number-zero.exp: bar2, 2nd next
    PASS: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar1_label_3
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar2_label_3
    ...
    
    commit 8c95582da8 "gdb: Add support for tracking the DWARF line table is-stmt
    field":
    ...
    PASS: gdb.dwarf2/dw2-line-number-zero.exp: bar1, 2nd next
    PASS: gdb.dwarf2/dw2-line-number-zero.exp: bar2, 2nd next
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar1_label_3
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar2_label_3
    ...
    
    commit d8cc8af6a1 "[gdb/symtab] Fix line-table end-of-sequence sorting",
    master:
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar1, 2nd next
    FAIL: gdb.dwarf2/dw2-line-number-zero.exp: bar2, 2nd next
    PASS: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar1_label_3
    PASS: gdb.dwarf2/dw2-line-number-zero.exp: continue to breakpoint: bar2_label_3
    ...
    
    The regression in test 2 at commit d8cc8af6a1 was filed as PR symtab/26243,
    where clang emits zero line numbers.
    
    The way to fix all tests is to make sure line number zero internally doesn't
    clash with special meaning values, and by handling it appropriately
    everywhere.  That however looks too intrusive for the GDB 10 release.
    
    Instead, we decide to ensure defined behaviour for line number zero by
    ignoring it.  This gives us back the test results from before commit
    d8cc8af6a1, fixing PR26243.
    
    We mark the FAILs for tests 3 and 4 as KFAILs.  Test 4 was already failing for
    the 9.2 release, and we consider the regression of test 3 from gdb 9.2 to gdb
    10 the cost for having defined behaviour.
    
    Build and reg-tested on x86_64-linux.
    
    gdb/ChangeLog:
    
    2020-07-25  Tom de Vries  <tdevries@suse.de>
    
            PR symtab/26243
            * dwarf2/read.c (lnp_state_machine::record_line): Ignore zero line
            entries.
    
    gdb/testsuite/ChangeLog:
    
    2020-07-25  Tom de Vries  <tdevries@suse.de>
    
            PR symtab/26243
            * gdb.dwarf2/dw2-line-number-zero.c: New test.
            * gdb.dwarf2/dw2-line-number-zero.exp: New file.
Comment 17 Tom de Vries 2020-07-24 22:33:38 UTC
Patch fixing regression and adding dwarf assembly test-case added, marking resolved-fixed.
Comment 18 Jaydeep Chauhan 2020-09-03 05:19:55 UTC
*** Bug 26538 has been marked as a duplicate of this bug. ***