[RFC,0/6] Step program considering the source column information

Message ID 20200516172632.4803-1-ssbssa@yahoo.de
Headers show
Series
  • Step program considering the source column information
Related show

Message

Kevin Buettner via Gdb-patches May 16, 2020, 5:26 p.m.
Basically, this implements the new commands nextc (nc) and stepc (sc),
which allow to step through the program until an instruction is reached,
that belongs to another source column (according to the debug information).

The current column location is visualized in the frame info, and in the TUI.

Also, the column information is added to 'maint info line-table' and the
python line table interface.

Since the frame info output is different, this certainly breaks the
testsuite, so this column indicator needs a parameter to disable, but I
wasn't concerned about this yet.

With the example code from PR25913, it looks like this:

(gdb) start
Temporary breakpoint 2 at 0x40162d: file gdb-25911.c, line 4.
Starting program: C:\src\tests\gdb-25911.exe

Temporary breakpoint 2, main () at gdb-25911.c:4
4         int a = 4;
              ^
(gdb) nc
6         a = 5; a = 6; a = 7;
            ^
(gdb) nc
6         a = 5; a = 6; a = 7;
                   ^
(gdb) nc
6         a = 5; a = 6; a = 7;
                          ^
(gdb) nc
8         return 0;


What do you think of this so far?


[PATCH 1/6] Add column information of dwarf to the symbol information
[PATCH 2/6] Implement nextc and stepc commands (PR gdb/25913)
[PATCH 3/6] Add column information to maint info line-table
[PATCH 4/6] Add LineTableEntry.column to python line table interface
[PATCH 5/6] Show column of current execution point in frame info (PR
[PATCH 6/6] Show column of current execution point in TUI

Comments

Kevin Buettner via Gdb-patches May 16, 2020, 6:45 p.m. | #1
Hi,

Cool!  A few years back, Antoine Tremblay prototyped this
as well, but it only worked with Clang, because back then
GCC didn't output column information.  I complained about it
to Jakub Jelinek, who in his usual awesomeness quickly implemented
GCC support.  :-)  Quite nice that we're finally getting closer to
actually making use of it in GDB.

You can still find Antoine's prototype here:

 https://github.com/hexa00/binutils-gdb/commits/statement-stepping

It would likely be interesting if you could take a look and compare
approaches.  You should be able to borrow any code you find useful, since
he was working for Ericsson at the time, and had a copyright assignment.

On the name of the new commands -- for a user, thinking in terms
"step until next column" doesn't make sense IMO.  What the user really wants
is "step until next statement".  Column information in the debug
info enables this, but it's an implementation detail.
In Antoine's version, he thus had "nexts" instead of "nextc", which
sounds better to me:

  add_com ("nexts", class_run, nexts_command, _("\
Step program by statement, proceeding through subroutine calls.\n\
Usage: nexts [N]\n\
Unlike \"steps\", if the current source line calls a subroutine,\n\
this command does not enter the subroutine, but instead steps over\n\
the call, in effect treating it as a single statement."));
  add_com_alias ("ns", "nexts", class_run, 1);

Thanks,
Pedro Alves
Kevin Buettner via Gdb-patches May 17, 2020, 12:08 a.m. | #2
Am Samstag, 16. Mai 2020, 20:45:30 MESZ hat Pedro Alves <palves@redhat.com> Folgendes geschrieben:

> Hi,

>

> Cool!  A few years back, Antoine Tremblay prototyped this

> as well, but it only worked with Clang, because back then

> GCC didn't output column information.  I complained about it

> to Jakub Jelinek, who in his usual awesomeness quickly implemented

> GCC support.  :-)  Quite nice that we're finally getting closer to

> actually making use of it in GDB.

>

> You can still find Antoine's prototype here:

>

> https://github.com/hexa00/binutils-gdb/commits/statement-stepping


I didn't know about that, interesting.
Is there some reason why this wasn't included in gdb back then?


> It would likely be interesting if you could take a look and compare

> approaches.  You should be able to borrow any code you find useful, since

> he was working for Ericsson at the time, and had a copyright assignment.


I just checked it out for a bit.

The actual implementation in process_event_stop_test() is a lot simpler,
I will have to try it out and compare the result, maybe that means mine
is unnecessary complicated.

And the calculation of the column indicator position is also more complicated
in mine, but that's because I had to account for the escape sequences of
the syntax highlighting.


> On the name of the new commands -- for a user, thinking in terms

> "step until next column" doesn't make sense IMO.  What the user really wants

> is "step until next statement".  Column information in the debug

> info enables this, but it's an implementation detail.

> In Antoine's version, he thus had "nexts" instead of "nextc", which

> sounds better to me:

>

>   add_com ("nexts", class_run, nexts_command, _("\

> Step program by statement, proceeding through subroutine calls.\n\

> Usage: nexts [N]\n\

> Unlike \"steps\", if the current source line calls a subroutine,\n\

> this command does not enter the subroutine, but instead steps over\n\

> the call, in effect treating it as a single statement."));

>   add_com_alias ("ns", "nexts", class_run, 1);


Yes, he has nexts (ns) and steps (ss), I don't really mind either way.
I used nextc/stepc because that was suggested in PR25913.


Hannes
Tom Tromey May 18, 2020, 4:21 p.m. | #3
>>>>> "Hannes" == Hannes Domani via Gdb-patches <gdb-patches@sourceware.org> writes:


Hannes> (gdb) nc
Hannes> 6         a = 5; a = 6; a = 7;
Hannes>             ^

It looks like maybe the caret is misplaced?

Hannes> What do you think of this so far?

I think it is fantastic.

Tom
Kevin Buettner via Gdb-patches May 18, 2020, 4:28 p.m. | #4
Am Montag, 18. Mai 2020, 18:21:34 MESZ hat Tom Tromey <tom@tromey.com> Folgendes geschrieben:

> >>>>> "Hannes" == Hannes Domani via Gdb-patches <gdb-patches@sourceware.org> writes:

>

> Hannes> (gdb) nc

> Hannes> 6        a = 5; a = 6; a = 7;

> Hannes>            ^

>

> It looks like maybe the caret is misplaced?


The caret should always be below the equal sign for this example, according
to the debug information (except the initialization, there it's below 'a').


Hannes
Kevin Buettner via Gdb-patches May 19, 2020, 12:27 p.m. | #5
On 5/16/20 2:26 PM, Hannes Domani via Gdb-patches wrote:
> Basically, this implements the new commands nextc (nc) and stepc (sc),

> which allow to step through the program until an instruction is reached,

> that belongs to another source column (according to the debug information).

> 

> The current column location is visualized in the frame info, and in the TUI.

> 

> Also, the column information is added to 'maint info line-table' and the

> python line table interface.

> 

> Since the frame info output is different, this certainly breaks the

> testsuite, so this column indicator needs a parameter to disable, but I

> wasn't concerned about this yet.

> 

> With the example code from PR25913, it looks like this:

> 

> (gdb) start

> Temporary breakpoint 2 at 0x40162d: file gdb-25911.c, line 4.

> Starting program: C:\src\tests\gdb-25911.exe

> 

> Temporary breakpoint 2, main () at gdb-25911.c:4

> 4         int a = 4;

>                ^

> (gdb) nc

> 6         a = 5; a = 6; a = 7;

>              ^

> (gdb) nc

> 6         a = 5; a = 6; a = 7;

>                     ^

> (gdb) nc

> 6         a = 5; a = 6; a = 7;

>                            ^

> (gdb) nc

> 8         return 0;

> 

> 

> What do you think of this so far?

> 

> 

> [PATCH 1/6] Add column information of dwarf to the symbol information

> [PATCH 2/6] Implement nextc and stepc commands (PR gdb/25913)

> [PATCH 3/6] Add column information to maint info line-table

> [PATCH 4/6] Add LineTableEntry.column to python line table interface

> [PATCH 5/6] Show column of current execution point in frame info (PR

> [PATCH 6/6] Show column of current execution point in TUI

> 


Thanks for working on this, it is really useful.

I'm guessing this series would probably handle the following situation 
very well:

https://sourceware.org/bugzilla/show_bug.cgi?id=21221
Kevin Buettner via Gdb-patches May 19, 2020, 4:02 p.m. | #6
Am Dienstag, 19. Mai 2020, 14:27:44 MESZ hat Luis Machado <luis.machado@linaro.org> Folgendes geschrieben:

> Thanks for working on this, it is really useful.

>

> I'm guessing this series would probably handle the following situation

> very well:

>

> https://sourceware.org/bugzilla/show_bug.cgi?id=21221


According to the debug info, the i initialization is on line 5, column 23.
And the rest of the for-loop is on line 5, column 5.

With the new column-based next-command, it goes back and forth between
them (but you have to wait a while for the inner loop to finish).

Debug session:

(gdb) start
Temporary breakpoint 1 at 0x40162d: file gdb-21221.c, line 5, column 23.
Starting program: C:\src\tests\gdb-21221.exe

Temporary breakpoint 1, main () at gdb-21221.c:5
5           for (unsigned int i = 0U; i < 0xFFFFFU; i++)
                              ^
(gdb) nc
5           for (unsigned int i = 0U; i < 0xFFFFFU; i++)
            ^
(gdb) nc
5           for (unsigned int i = 0U; i < 0xFFFFFU; i++)
                              ^
(gdb) nc
5           for (unsigned int i = 0U; i < 0xFFFFFU; i++)
            ^
(gdb) l
1       int main (void)
2       {
3         while (1)
4         {
5           for (unsigned int i = 0U; i < 0xFFFFFU; i++)
6           {
7             ;
8           }
9         }
10      }
(gdb) disas
Dump of assembler code for function main:
   0x0000000000401620 <+0>:     push   %rbp
   0x0000000000401621 <+1>:     mov    %rsp,%rbp
   0x0000000000401624 <+4>:     sub    $0x30,%rsp
   0x0000000000401628 <+8>:     callq  0x401700 <__main>
   0x000000000040162d <+13>:    movl   $0x0,-0x4(%rbp)
   0x0000000000401634 <+20>:    jmp    0x40163a <main+26>
   0x0000000000401636 <+22>:    addl   $0x1,-0x4(%rbp)
   0x000000000040163a <+26>:    cmpl   $0xffffe,-0x4(%rbp)
   0x0000000000401641 <+33>:    jbe    0x401636 <main+22>
   0x0000000000401643 <+35>:    jmp    0x40162d <main+13>
End of assembler dump.
(gdb) maint info line-table gdb-21221.c
objfile: C:\src\tests\gdb-21221.exe ((struct objfile *) 0x11f4e670)
compunit_symtab: ((struct compunit_symtab *) 0x11f71890)
symtab: C:\src\tests\gdb-21221.c ((struct symtab *) 0x11f71910)
linetable: ((struct linetable *) 0x1204fde0):
INDEX  LINE   COLUMN ADDRESS            IS-STMT
0      2      1      0x0000000000401620 Y
1      2      1      0x0000000000401628 Y
2      5      23     0x000000000040162d Y
3      5      5      0x0000000000401634 Y
4      END           0x0000000000401645 Y
Tom de Vries May 27, 2020, 3:33 p.m. | #7
On 16-05-2020 19:26, Hannes Domani via Gdb-patches wrote:
> Basically, this implements the new commands nextc (nc) and stepc (sc),

> which allow to step through the program until an instruction is reached,

> that belongs to another source column (according to the debug information).

> 

> The current column location is visualized in the frame info, and in the TUI.

> 

> Also, the column information is added to 'maint info line-table' and the

> python line table interface.

> 

> Since the frame info output is different, this certainly breaks the

> testsuite, so this column indicator needs a parameter to disable, but I

> wasn't concerned about this yet.

> 

> With the example code from PR25913, it looks like this:

> 

> (gdb) start

> Temporary breakpoint 2 at 0x40162d: file gdb-25911.c, line 4.

> Starting program: C:\src\tests\gdb-25911.exe

> 

> Temporary breakpoint 2, main () at gdb-25911.c:4

> 4         int a = 4;

>               ^

> (gdb) nc

> 6         a = 5; a = 6; a = 7;

>             ^

> (gdb) nc

> 6         a = 5; a = 6; a = 7;

>                    ^

> (gdb) nc

> 6         a = 5; a = 6; a = 7;

>                           ^

> (gdb) nc

> 8         return 0;

> 

> 

> What do you think of this so far?

> 


Very nice :)

As I've just learned by looking at this (
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95360 ) PR, interesting
code in relation to this patch series is dwarf_record_line_p.

The function implements filtering of line-table elements, and has as
related test-case gdb.dwarf2/dw2-single-line-discriminators.exp.

If we disable the filtering (by returning 1 at the end instead of 0), we
get for test-case gdb.dwarf2/dw2-single-line-discriminators.exp:
...
Temporary breakpoint 2, main () at
gdb.dwarf2/dw2-single-line-discriminators.c:26
26        x = 0;
(gdb) n
28        for (i = 0; i < 10; ++i) continue; /* stepi line */
(gdb) si
28        for (i = 0; i < 10; ++i) continue; /* stepi line */
...

That is: no progress is visible after the stepi.  If we re-enable the
filtering, we have:
...
Temporary breakpoint 1, main () at
gdb.dwarf2/dw2-single-line-discriminators.c:26
26        x = 0;
(gdb) n
28        for (i = 0; i < 10; ++i) continue; /* stepi line */
(gdb) si
0x00000000004004cd      28        for (i = 0; i < 10; ++i) continue; /*
stepi line */
...

So, progress is visible.

If we now use your patch series, and with the filtering enabled, we have:
...
Temporary breakpoint 1, main () at
gdb.dwarf2/dw2-single-line-discriminators.c:26
26        x = 0;
          ^
(gdb) n
28        for (i = 0; i < 10; ++i) continue; /* stepi line */
               ^
(gdb) si
0x00000000004004cd      28        for (i = 0; i < 10; ++i) continue; /*
stepi line */
                                       ^
(gdb)
0x00000000004004d1      28        for (i = 0; i < 10; ++i) continue; /*
stepi line */
                                       ^
(gdb)
0x00000000004004d3      28        for (i = 0; i < 10; ++i) continue; /*
stepi line */
                                       ^
(gdb)
0x00000000004004d5      28        for (i = 0; i < 10; ++i) continue; /*
stepi line */
                                       ^
...

So, we see progress in the insn addresses, but the column does not progress.

OTOH, if we disable filtering:
...
Temporary breakpoint 1, main () at
gdb.dwarf2/dw2-single-line-discriminators.c:26
26        x = 0;
          ^
(gdb) n
28        for (i = 0; i < 10; ++i) continue; /* stepi line */
               ^
(gdb) si
28        for (i = 0; i < 10; ++i) continue; /* stepi line */
               ^
(gdb) si
0x00000000004004d1      28        for (i = 0; i < 10; ++i) continue; /*
stepi line */
                                       ^
(gdb) si
28        for (i = 0; i < 10; ++i) continue; /* stepi line */
                                   ^
(gdb) si
28        for (i = 0; i < 10; ++i) continue; /* stepi line */
                              ^
(gdb) si
0x00000000004004d8      28        for (i = 0; i < 10; ++i) continue; /*
stepi line */
                                                      ^
...
we don't see progress after the first stepi, but eventually we do see
progress in the column.

Looking at the line-info:
...
  [0x00000147]  Set column to 8
  [0x00000149]  Special opcode 161: advance Address by 11 to 0x4004c6
and Line by 2 to 28
  [0x0000014a]  Extended opcode 4: set Discriminator to 4
  [0x0000014e]  Special opcode 103: advance Address by 7 to 0x4004cd and
Line by 0 to 28
...
perhaps we we should collapse entries that have the same column, so
something like this in dwarf_record_line_p:
...
  if (line != last_line)
    return 1;
  if (colum != last_column)
    return 1;
  return 0;
...

Thanks,
- Tom
Kevin Buettner via Gdb-patches May 27, 2020, 4:04 p.m. | #8
Am Mittwoch, 27. Mai 2020, 17:33:37 MESZ hat Tom de Vries <tdevries@suse.de> Folgendes geschrieben:

> On 16-05-2020 19:26, Hannes Domani via Gdb-patches wrote:

> > Basically, this implements the new commands nextc (nc) and stepc (sc),

> > which allow to step through the program until an instruction is reached,

> > that belongs to another source column (according to the debug information).

> >

> > The current column location is visualized in the frame info, and in the TUI.

> >

> > Also, the column information is added to 'maint info line-table' and the

> > python line table interface.

> >

> > Since the frame info output is different, this certainly breaks the

> > testsuite, so this column indicator needs a parameter to disable, but I

> > wasn't concerned about this yet.

> >

> > With the example code from PR25913, it looks like this:

> >

> > (gdb) start

> > Temporary breakpoint 2 at 0x40162d: file gdb-25911.c, line 4.

> > Starting program: C:\src\tests\gdb-25911.exe

> >

> > Temporary breakpoint 2, main () at gdb-25911.c:4

> > 4        int a = 4;

> >              ^

> > (gdb) nc

> > 6        a = 5; a = 6; a = 7;

> >            ^

> > (gdb) nc

> > 6        a = 5; a = 6; a = 7;

> >                    ^

> > (gdb) nc

> > 6        a = 5; a = 6; a = 7;

> >                          ^

> > (gdb) nc

> > 8        return 0;

> >

> >

> > What do you think of this so far?

> >

>

> Very nice :)

>

> As I've just learned by looking at this (

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95360 ) PR, interesting

> code in relation to this patch series is dwarf_record_line_p.

>

> The function implements filtering of line-table elements, and has as

> related test-case gdb.dwarf2/dw2-single-line-discriminators.exp.

>

> If we disable the filtering (by returning 1 at the end instead of 0), we

> get for test-case gdb.dwarf2/dw2-single-line-discriminators.exp:

> ...

> Temporary breakpoint 2, main () at

> gdb.dwarf2/dw2-single-line-discriminators.c:26

> 26        x = 0;

> (gdb) n

> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

> (gdb) si

> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

> ...

>

> That is: no progress is visible after the stepi.  If we re-enable the

> filtering, we have:

> ...

> Temporary breakpoint 1, main () at

> gdb.dwarf2/dw2-single-line-discriminators.c:26

> 26        x = 0;

> (gdb) n

> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

> (gdb) si

> 0x00000000004004cd      28        for (i = 0; i < 10; ++i) continue; /*

> stepi line */

> ...

>

> So, progress is visible.

>

> If we now use your patch series, and with the filtering enabled, we have:

> ...

> Temporary breakpoint 1, main () at

> gdb.dwarf2/dw2-single-line-discriminators.c:26

> 26        x = 0;

>           ^

> (gdb) n

> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>               ^

> (gdb) si

> 0x00000000004004cd      28        for (i = 0; i < 10; ++i) continue; /*

> stepi line */

>                                       ^

> (gdb)

> 0x00000000004004d1      28        for (i = 0; i < 10; ++i) continue; /*

> stepi line */

>                                       ^

> (gdb)

> 0x00000000004004d3      28        for (i = 0; i < 10; ++i) continue; /*

> stepi line */

>                                       ^

> (gdb)

> 0x00000000004004d5      28        for (i = 0; i < 10; ++i) continue; /*

> stepi line */

>                                       ^

> ...

>

> So, we see progress in the insn addresses, but the column does not progress.

>

> OTOH, if we disable filtering:

> ...

> Temporary breakpoint 1, main () at

> gdb.dwarf2/dw2-single-line-discriminators.c:26

> 26        x = 0;

>           ^

> (gdb) n

> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>               ^

> (gdb) si

> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>               ^

> (gdb) si

> 0x00000000004004d1      28        for (i = 0; i < 10; ++i) continue; /*

> stepi line */

>                                       ^

> (gdb) si

> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>                                   ^

> (gdb) si

> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>                               ^

> (gdb) si

> 0x00000000004004d8      28        for (i = 0; i < 10; ++i) continue; /*

> stepi line */

>                                                       ^

> ...

> we don't see progress after the first stepi, but eventually we do see

> progress in the column.

>

> Looking at the line-info:

> ...

>   [0x00000147]  Set column to 8

>   [0x00000149]  Special opcode 161: advance Address by 11 to 0x4004c6

> and Line by 2 to 28

>   [0x0000014a]  Extended opcode 4: set Discriminator to 4

>   [0x0000014e]  Special opcode 103: advance Address by 7 to 0x4004cd and

> Line by 0 to 28

> ...

> perhaps we we should collapse entries that have the same column, so

> something like this in dwarf_record_line_p:

> ...

>   if (line != last_line)

>     return 1;

>   if (colum != last_column)

>     return 1;

>

>   return 0;

>

> ...


Interesting.
I'm just wondering, if dwarf_record_line_p merges all entries of the same line,
why does my column-based stepping even work at all?

Is it because of line_has_non_zero_discriminator?
If yes, what is the discriminator?


Hannes
Tom de Vries June 2, 2020, 9:08 a.m. | #9
On 27-05-2020 18:04, Hannes Domani via Gdb-patches wrote:
>  Am Mittwoch, 27. Mai 2020, 17:33:37 MESZ hat Tom de Vries <tdevries@suse.de> Folgendes geschrieben:

> 

>> On 16-05-2020 19:26, Hannes Domani via Gdb-patches wrote:

>>> Basically, this implements the new commands nextc (nc) and stepc (sc),

>>> which allow to step through the program until an instruction is reached,

>>> that belongs to another source column (according to the debug information).

>>>

>>> The current column location is visualized in the frame info, and in the TUI.

>>>

>>> Also, the column information is added to 'maint info line-table' and the

>>> python line table interface.

>>>

>>> Since the frame info output is different, this certainly breaks the

>>> testsuite, so this column indicator needs a parameter to disable, but I

>>> wasn't concerned about this yet.

>>>

>>> With the example code from PR25913, it looks like this:

>>>

>>> (gdb) start

>>> Temporary breakpoint 2 at 0x40162d: file gdb-25911.c, line 4.

>>> Starting program: C:\src\tests\gdb-25911.exe

>>>

>>> Temporary breakpoint 2, main () at gdb-25911.c:4

>>> 4        int a = 4;

>>>               ^

>>> (gdb) nc

>>> 6        a = 5; a = 6; a = 7;

>>>             ^

>>> (gdb) nc

>>> 6        a = 5; a = 6; a = 7;

>>>                     ^

>>> (gdb) nc

>>> 6        a = 5; a = 6; a = 7;

>>>                           ^

>>> (gdb) nc

>>> 8        return 0;

>>>

>>>

>>> What do you think of this so far?

>>>

>>

>> Very nice :)

>>

>> As I've just learned by looking at this (

>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95360 ) PR, interesting

>> code in relation to this patch series is dwarf_record_line_p.

>>

>> The function implements filtering of line-table elements, and has as

>> related test-case gdb.dwarf2/dw2-single-line-discriminators.exp.

>>

>> If we disable the filtering (by returning 1 at the end instead of 0), we

>> get for test-case gdb.dwarf2/dw2-single-line-discriminators.exp:

>> ...

>> Temporary breakpoint 2, main () at

>> gdb.dwarf2/dw2-single-line-discriminators.c:26

>> 26        x = 0;

>> (gdb) n

>> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>> (gdb) si

>> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>> ...

>>

>> That is: no progress is visible after the stepi.  If we re-enable the

>> filtering, we have:

>> ...

>> Temporary breakpoint 1, main () at

>> gdb.dwarf2/dw2-single-line-discriminators.c:26

>> 26        x = 0;

>> (gdb) n

>> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>> (gdb) si

>> 0x00000000004004cd      28        for (i = 0; i < 10; ++i) continue; /*

>> stepi line */

>> ...

>>

>> So, progress is visible.

>>

>> If we now use your patch series, and with the filtering enabled, we have:

>> ...

>> Temporary breakpoint 1, main () at

>> gdb.dwarf2/dw2-single-line-discriminators.c:26

>> 26        x = 0;

>>            ^

>> (gdb) n

>> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>>                ^

>> (gdb) si

>> 0x00000000004004cd      28        for (i = 0; i < 10; ++i) continue; /*

>> stepi line */

>>                                        ^

>> (gdb)

>> 0x00000000004004d1      28        for (i = 0; i < 10; ++i) continue; /*

>> stepi line */

>>                                        ^

>> (gdb)

>> 0x00000000004004d3      28        for (i = 0; i < 10; ++i) continue; /*

>> stepi line */

>>                                        ^

>> (gdb)

>> 0x00000000004004d5      28        for (i = 0; i < 10; ++i) continue; /*

>> stepi line */

>>                                        ^

>> ...

>>

>> So, we see progress in the insn addresses, but the column does not progress.

>>

>> OTOH, if we disable filtering:

>> ...

>> Temporary breakpoint 1, main () at

>> gdb.dwarf2/dw2-single-line-discriminators.c:26

>> 26        x = 0;

>>            ^

>> (gdb) n

>> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>>                ^

>> (gdb) si

>> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>>                ^

>> (gdb) si

>> 0x00000000004004d1      28        for (i = 0; i < 10; ++i) continue; /*

>> stepi line */

>>                                        ^

>> (gdb) si

>> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>>                                    ^

>> (gdb) si

>> 28        for (i = 0; i < 10; ++i) continue; /* stepi line */

>>                                ^

>> (gdb) si

>> 0x00000000004004d8      28        for (i = 0; i < 10; ++i) continue; /*

>> stepi line */

>>                                                        ^

>> ...

>> we don't see progress after the first stepi, but eventually we do see

>> progress in the column.

>>

>> Looking at the line-info:

>> ...

>>    [0x00000147]  Set column to 8

>>    [0x00000149]  Special opcode 161: advance Address by 11 to 0x4004c6

>> and Line by 2 to 28

>>    [0x0000014a]  Extended opcode 4: set Discriminator to 4

>>    [0x0000014e]  Special opcode 103: advance Address by 7 to 0x4004cd and

>> Line by 0 to 28

>> ...

>> perhaps we we should collapse entries that have the same column, so

>> something like this in dwarf_record_line_p:

>> ...

>>    if (line != last_line)

>>      return 1;

>>    if (colum != last_column)

>>      return 1;

>>

>>    return 0;

>>

>> ...

> 


Sorry for the late reply, I didn't notice this earlier (not on To/CC
list for some reason).

> Interesting.

> I'm just wondering, if dwarf_record_line_p merges all entries of the same line,

> why does my column-based stepping even work at all?

> 

> Is it because of line_has_non_zero_discriminator?


Yes. ( See also https://sourceware.org/bugzilla/show_bug.cgi?id=17276 ).

> If yes, what is the discriminator?


DWARF 4 standard, 6.2.2 State Machine Registers :
...
An unsigned integer identifying the block to which the current
instruction belongs. Discriminator values are assigned arbitrarily by
the DWARF producer and serve to distinguish among multiple blocks that
may all be associated with the same source file, line, and column. Where
only one lock exists for a given source position, the discriminator
value should be zero.
...

Thanks,
- Tom